Cria um arquivo com tamanho de arquivo limitado

4

Eu escrevi um programa servidor (Ubuntu 14.04 LTS Server) - cliente-java.

Com este programa, posso enviar um texto do meu android-smartphone para o meu servidor, salvando-o no arquivo receivedData .

O programa está sendo executado sob um usuário que não tem shell designado e nenhum acesso a dados ou programas sensíveis por padrão.

O único problema de segurança que consigo pensar está ficando sem memória devido a um monte de arquivos gigabyte receivedData que não tem verificação de tamanho. Ou, claro, um ataque DoS, mas eu não acho que o meu servidor é tão importante ...

O programa é apenas para fins de aprendizado e não deve ser usado por nenhum cliente / hacker (é claro;)), mas você nunca mais ...

Então, alguém pode me dizer se é possível criar diretamente um arquivo receivedData com um tamanho de arquivo limitado. No momento em que ele atinge o tamanho do arquivo, ele deve negar receivedData , evitando que ele cause uma OOM.

Se não, precisarei implementar isso no programa java ...

    
por Mike 26.05.2015 / 13:27

4 respostas

16

Existem duas maneiras de fazer isso:

  • usando o utilitário ulimit shell ou usando a chamada do sistema setrlimit (que é o que ulimit chama por sua vez).
  • usando cotas do sistema de arquivos e um usuário especial para o processo do servidor restringirá o uso do total desse usuário

ulimit / setrlimit

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

Não sei como é possível invocar a função setrlimit do Java, mas A pergunta do U & L pode ajudar. Como alternativa, envolva o servidor Java em um script:

#! /bin/bash
ulimit -f 1073741824   # 1GB
java ....

Cotas do sistema de arquivos:

Estou assumindo um sistema de arquivos ext4, não tenho certeza sobre os outros. Primeiro, precisamos ativar a quota no sistema de arquivos. Edite /etc/fstab e adicione usrquota às opções de montagem da partição apropriada. Se estamos fazendo isso para / , por exemplo, a entrada final seria algo como:

UUID=... /               ext4    errors=remount-ro,usrquota 0       1

Em seguida, ative-o após a reinicialização:

sudo quotaon /

Suponho que seu servidor seja executado como um usuário diferente (digamos, restricted_user ). Se não, crie um se não quiser que seus processos normais sejam afetados.

Então faça:

sudo edquota restricted_user

O que abrirá um editor.

Disk quotas for user restricted_user (uid 1001):
  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/sdd1                   1087940    943718   1048576       9956        0        0

Defina os limites flexíveis e rígidos para os valores apropriados (eles são blocos de 1024 bytes, portanto, divida seu limite por 1024). Salve e saia.

Em seguida, o usuário não poderá exceder um total de uso de 1G nesse sistema de arquivos, contando todos os arquivos pertencentes a eles.

Naturalmente, você ainda deve verificar o tamanho no seu programa de servidor.

    
por muru 26.05.2015 / 14:11
5

ATUALIZAÇÃO:

A resposta do muru é perfeita para o tamanho do arquivo, estou aqui dando uma solução sobre como dimensionar um diretório em si, não apenas um arquivo.

Não existe tal coisa direta, já que o sistema de arquivos lida com uma pasta como um arquivo de arquivos e seu limite é todo o próprio sistema de arquivos.

Então, como solução para o seu problema, você pode criar um truque para criar um sistema de arquivos virtual e montá-lo em um diretório específico (vazio).

crie o ponto de montagem do sistema de arquivos virtual para montar (~ / test for me)

mkdir ~/test

crie um arquivo cheio de / dev / zero, grande o suficiente para o tamanho máximo que você deseja reservar para o sistema de arquivos virtual (eu estou fazendo aqui por 1MB)

dd if=/dev/zero of=test.img bs=1024 count=0 seek=1024

formate este arquivo com um sistema de arquivos ext4

 mke2fs test.img

monte o espaço em disco recém-formatado no diretório que você criou como ponto de montagem

mount -o loop test.img ~/test

Em seguida, use este diretório

    
por Maythux 26.05.2015 / 13:38
2

Eu diria que é mais seguro verificar o tamanho do arquivo dentro do programa java.

Você pode anexar a qualquer arquivo em que tenha acesso de gravação, desde que haja espaço suficiente na partição, portanto, não é possível limitar o tamanho de um arquivo diretamente.

A única coisa em que consigo pensar é criar uma partição apenas para esse arquivo, portanto, o tamanho do arquivo será limitado ao tamanho da partição. Além disso, se você formatar a partição como FAT32, o arquivo poderá ter um tamanho máximo de 4 GiB.

    
por s3lph 26.05.2015 / 13:36
0

Sem ver seu código, é difícil dizer se seu aplicativo seria OOM ou não.

Geralmente, você lê um bloco gerenciável de dados (digamos, 1 MB) do soquete e grava esse bloco de dados diretamente em um arquivo. Dessa forma, você nunca armazenaria mais do que o pedaço temporário na memória a qualquer momento.

Normalmente, parece que:

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);
};

Você pode então adicionar um contador ao loop while para contar quantos bytes foram gravados no arquivo e terminar o soquete se ele ultrapassar um valor predeterminado ou estiver consumindo todo o espaço em disco disponível.

    
por Alastair McCormack 26.05.2015 / 15:59

Tags