GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo evitar que un proceso escriba archivos

¿Qué tal si creamos un chroot vacío y luego montamos el sistema de archivos principal como de solo lectura dentro del chroot?

Probablemente debería ser algo como esto para crear un montaje de enlace de solo lectura:

mount --bind /foo/ /path/to/chroot/
mount -o remount,ro /path/to/chroot/

Puede enlazar-montar otros directorios a los que desee que la cárcel también tenga acceso de escritura. Tenga cuidado si necesita enlazar directorios especiales de montaje (/dev/, /proc/, /sys/), montarlos tal cual puede ser inseguro.


Parece que la herramienta adecuada para este trabajo es fseccomp Basado en sync-ignoring f código de Bastian Blank, se me ocurrió este archivo relativamente pequeño que hace que todos sus elementos secundarios no puedan abrir un archivo para escribir:

/*
 * Copyright (C) 2013 Joachim Breitner <[email protected]>
 *
 * Based on code Copyright (C) 2013 Bastian Blank <[email protected]>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define _GNU_SOURCE 1
#include <errno.h>
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define filter_rule_add(action, syscall, count, ...) \
  if (seccomp_rule_add(filter, action, syscall, count, ##__VA_ARGS__)) abort();

static int filter_init(void)
{
  scmp_filter_ctx filter;

  if (!(filter = seccomp_init(SCMP_ACT_ALLOW))) abort();
  if (seccomp_attr_set(filter, SCMP_FLTATR_CTL_NNP, 1)) abort();
  filter_rule_add(SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY));
  filter_rule_add(SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1, SCMP_A1(SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR));
  return seccomp_load(filter);
}

int main(__attribute__((unused)) int argc, char *argv[])
{
  if (argc <= 1)
  {
    fprintf(stderr, "usage: %s COMMAND [ARG]...\n", argv[0]);
    return 2;
  }

  if (filter_init())
  {
    fprintf(stderr, "%s: can't initialize seccomp filter\n", argv[0]);
    return 1;
  }

  execvp(argv[1], &argv[1]);

  if (errno == ENOENT)
  {
    fprintf(stderr, "%s: command not found: %s\n", argv[0], argv[1]);
    return 127;
  }

  fprintf(stderr, "%s: failed to execute: %s: %s\n", argv[0], argv[1], strerror(errno));
  return 1;
}

Aquí puede ver que todavía es posible leer archivos:

[[email protected]:1] Wed, der 06.03.2013 um 12:58 Uhr Keep Smiling :-)
> ls test
ls: cannot access test: No such file or directory
> echo foo > test
bash: test: Permission denied
> ls test
ls: cannot access test: No such file or directory
> touch test
touch: cannot touch 'test': Permission denied
> head -n 1 no-writes.c # reading still works
/*

No impide borrar archivos, ni moverlos, ni otras operaciones de archivos además de abrirlos, pero eso podría agregarse.

Una herramienta que permite esto sin tener que escribir código C es syscall_limiter.


¿Considerarías escribir un sustituto de open(…)? y cargarlo usando LD_PRELOAD?


Linux
  1. Cómo crear un video a partir de archivos PDF en Linux

  2. Cómo determinar qué proceso está escribiendo en el disco en Linux

  3. ¿Cómo obtener el valor de retorno de CHILD PROCESS?

  4. Cómo distinguir binarios de archivos de texto en Linux

  5. Cómo obtener un proceso secundario del proceso principal

Cómo evitar que se agote el tiempo de espera de SSH

Cómo prevenir y recuperarse de la eliminación accidental de archivos en Linux

Cómo descargar archivos desde servidores Linux remotos

Cómo encontrar el nombre del proceso a partir de su PID

¿Cómo evitar ir a SWAP?

¿Cómo eliminar caracteres no válidos de los nombres de archivo?