M BUZZ CRAZE NEWS
// general

Create a file with limited file size

By Jessica Wood

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...

2

4 Answers

There are two ways this can be done:

  • using the ulimit shell utility, or using the setrlimit system call (which is what ulimit calls 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 1

Then 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_user

Which 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 0

Set 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.

10

UPDATE:

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 ~/test

create 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=1024

format this file with an ext4 filesystem

 mke2fs test.img

mount the newly formatted disk space in the directory you've created as mount point

mount -o loop test.img ~/test

Then use this directory

4

I'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.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy