Create a file with limited file size
I have written a server(Ubuntu 14.04 LTS Server) - client - java program.
With this program I can send a text from my android-smartphone to my server saving it to the receivedData file.
The program is running under a user which has no shell assigned and no access to sensitive data or programs by default.
The only security issue I can think of is running out of memory due to a tons of gigabyte receivedData file which has no size check. Or, of course a DoS attack but I do not think my server is that important...
The program is just for learning purposes and shall not be used by any clients/hackers(of course ;)) but you never now..
So, can anyone tell me if it is possible to directly create a file receivedData with a limited file size. At the moment it reaches the file size it should deny receivedData preventing it from causing an OOM.
If not I will need to implement that into the java program...
24 Answers
There are two ways this can be done:
- using the
ulimitshell utility, or using thesetrlimitsystem call (which is whatulimitcalls in turn). - using filesystem quotas, and a special user for the server process, will restrict the total usage of that user
ulimit/setrlimit
From man 2 setrlimit:
RLIMIT_FSIZE The maximum size of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal. By default, this signal terminates a process, but a process can catch this signal instead, in which case the relevant system call (e.g., write(2), truncate(2)) fails with the error EFBIG.I'm not sure how one could invoke the setrlimit function from Java, but this U&L question might help. Alternatively, wrap the Java server in a script:
#! /bin/bash
ulimit -f 1073741824 # 1GB
java ....Filesystem Quotas:
I'm assuming an ext4 filesystem, I'm unsure about others. First, we need to enable quota on the filesystem. Edit /etc/fstab, and add usrquota to the mount options of the appropriate partition. If we're doing this for /, for example, the final entry would look something like:
UUID=... / ext4 errors=remount-ro,usrquota 0 1Then enable it after restarting:
sudo quotaon /I'll assume your server is run as a different user (say restricted_user). If not, create one if you don't want your normal processes to be affected.
Then do:
sudo edquota restricted_userWhich will open an editor.
Disk quotas for user restricted_user (uid 1001): Filesystem blocks soft hard inodes soft hard /dev/sdd1 1087940 943718 1048576 9956 0 0Set the soft and hard limits to the appropriate values (they're 1024-byte blocks, so divide your limit by 1024). Save and quit.
Then the user will not be able to exceed a total of 1G usage on that filesystem, counting all files owned by them.
Naturally, you should still check the size in your server program.
10UPDATE:
The answer by muru is perfect for file size, I'm here giving a solution how to size a directory itself, not just a file.
There is no such thing direct since filesystem deal with a folder as file of files and its limit is the whole filesystem itself.
So as a workaround for your problem you can do a trick creating a virtual filesystem and mount it on a specific (empty) directory.
create the mount point of the virtual file system to mount on (~/test for me)
mkdir ~/testcreate a file full of /dev/zero, large enough to the maximum size you want to reserve for the virtual filesystem (i'm doing here for 1MB)
dd if=/dev/zero of=test.img bs=1024 count=0 seek=1024format this file with an ext4 filesystem
mke2fs test.imgmount the newly formatted disk space in the directory you've created as mount point
mount -o loop test.img ~/testThen use this directory
4I'd say it's safest to check the file size inside the java program.
You can append to any file you have write access to, as long as there is enough space in the partition, so you cannot limit a file's size directly.
The only thing I can think of is to create a partition only for this file, so the file size will be limited to the partition's size. Also, if you'd format the partition as FAT32, the file could have a maximum size of 4 GiB.
Without seeing your code, it's hard to tell if your application would OOM or not.
Usually, you would read a manageable chunk of data (say 1MB) from the socket and write that chunk of data directly to a file. That way, you'd never store more than the temporary chunk in memory at any one time.
Typically this looks like:
FileOutputStream fos = new FileOutputStream("receivedData");
InputStream is = clientSocket.getInputStream();
byte[] buffer = new byte[1024];
int read;
while((read = is.read(buffer)) != -1) { fos.write(buffer);
};You could then add a counter to the while loop to count how many bytes have been written to the file and terminate the socket should it go over a predetermined amount or is getting close to consuming all available disk space.
More in general
"Zoraya ter Beek, age 29, just died by assisted suicide in the Netherlands. She was physically healthy, but psychologically depressed. It's an abomination that an entire society would actively facilitate, even encourage, someone ending their own life because they had no hope. Th…"