Ao executar um script de shell, como você pode protegê-lo de sobrescrever ou truncar arquivos?

1

Se, durante a execução de um aplicativo, uma das bibliotecas compartilhadas que ele usa for gravada ou truncada, o aplicativo falhará. Mover o arquivo ou removê-lo por atacado com 'rm' não causará uma falha, porque o SO (neste caso, mas eu presumo que isso seja verdade no Linux e em outros * nix também) é inteligente o suficiente para não excluir o inode associado o arquivo enquanto qualquer processo o abrir.

Eu tenho um script de shell que executa a instalação de bibliotecas compartilhadas. Às vezes, ele pode ser usado para reinstalar versões de bibliotecas compartilhadas que já estavam instaladas, sem uma desinstalação primeiro. Como os aplicativos podem estar usando as bibliotecas compartilhadas já instaladas, é importante que o script seja inteligente o suficiente para rm os arquivos ou movê-los para fora do caminho (por exemplo, para uma pasta 'excluída' que o cron poderia esvaziar de cada vez quando não sabemos será executado) antes de instalar os novos, para que não sejam sobrescritos ou truncados.

Infelizmente, recentemente um aplicativo falhou logo após a instalação. Coincidência? É difícil dizer. A solução real aqui é mudar para um método de instalação mais robusto do que um script de shell gigantesco antigo, mas seria bom ter alguma proteção extra até que o switch seja feito. Existe alguma maneira de quebrar um script de shell para protegê-lo de sobrescrever ou truncar arquivos (e, idealmente, falhando alto), mas ainda permitindo que eles sejam movidos ou rm'd?

As permissões de arquivo padrão UNIX não funcionam porque você não pode distinguir mover / remover de sobrescrever / truncar. Os aliases podem funcionar, mas não tenho certeza de quais inteiros de comandos precisam ser aliados. Eu imagino algo como treliça / strace, exceto antes de cada ação que ele verifica contra um filtro se realmente o faz. Não preciso de uma solução perfeita que funcione mesmo contra um script intencionalmente malicioso.

Idéias que tenho até agora:

  • Alias cp para GNU cp (não é o padrão, já que estou no Solaris) e uso a opção --remove-destination.
  • Alias install to GNU install e use a opção --backup. Pode ser inteligente o suficiente para mover o arquivo existente para o nome do arquivo de backup em vez de fazer uma cópia, preservando assim o inode.
  • "set noclobber" em ~ / .bashrc para que o redirecionamento de E / S não substitua arquivos
por Joseph Garvin 07.03.2010 / 02:52

5 respostas

2

Use o utilitário install - é para isso.

    
por 07.03.2010 / 09:56
1

Ao instalar um software, especialmente ao instalar um software existente, o modo de operação normal de segurança é (ou eu quero dizer 'deve ser'?):

  • Criar novo arquivo no diretório de destino sob o nome temporário t1
  • Definir permissões (proprietário, grupo, modo, ACL, ...)
  • Mover arquivo antigo para o nome temporário t2
  • Mova o novo arquivo t1 para o nome permanente
  • Finalmente, exclua t2

Se algo der errado enquanto você estiver copiando coisas, você não danificou sua instalação existente. Isso supõe que você tenha espaço livre em disco suficiente, é claro - mas o disco é barato.

Se você estiver escrevendo seus próprios instaladores, poderá fazer algo semelhante a isso. Se você estiver usando instaladores de outras pessoas, você terá dificuldades para lidar com suas peculiaridades. Em última análise, você precisa reclamar com os fornecedores. Mas observe que, se você tentar mexer nos comandos padrão, é provável que as mudanças voltem e mordam você.

    
por 07.03.2010 / 08:47
0

Minha primeira inclinação foi sugerir 'set noclobber' em ~ / .bashrc.

Segundo pensamento: o Solaris tem lsof, fuser ou fstat? Estes podem verificar se outro processo tem um arquivo aberto.

Você também pode tentar algo assim:

safecp() { 
  source=$1
  dest=$2
  dest_dir=$(dirname dest)
  [ -d $dest_dir] || mkdir $dest_dir/temp && mv $dest $dest_dir/temp && cp $source $temp 
}
    
por 07.03.2010 / 03:19
0

Acho que o rsync pode ser a ferramenta para isso. Você pode querer uma combinação de mudanças de execução ou itemize para atender às suas necessidades exatas. A opção --ignore-existing também pode ser interessante.

    
por 07.03.2010 / 03:21
0

A outra coisa a considerar é que usar o 'cp' entre os limites do sistema de arquivos irá gravar dados no inode atual, enquanto o cp dentro do mesmo sistema de arquivos será desvinculado do arquivo antigo e vinculado ao novo.

    
por 10.03.2010 / 14:49