프로세스가 파일에 쓰는 것을 중지하는 방법

프로세스가 파일에 쓰는 것을 중지하는 방법

쓰기용 파일을 만들거나 열 수 없도록 Linux에서 명령을 실행하고 싶습니다. 여전히 정상적으로 파일을 읽을 수 있어야 하며(따라서 빈 chroot는 옵션이 아님) 이미 열려 있는 파일(특히 stdout)에 계속 쓸 수 있어야 합니다.

파일을 일부 디렉터리(예: 현재 디렉터리)에 계속 쓸 수 있으면 보너스 포인트가 됩니다.

저는 전체 시스템에 대해 AppArmor 또는 SELinux와 같은 구성을 포함하지 않고 루트 권한도 포함하지 않는 프로세스 로컬 솔루션을 찾고 있습니다. 그러나 커널 모듈 설치가 필요할 수 있습니다.

파일을 생성하는 기능이 있다면 참 편하고 좋을 것 같은 기능을 찾아보고 있습니다. ulimit는 이 사용 사례를 다루는 경우 또 다른 편리한 방법입니다.

답변1

빈 chroot를 생성하고 chroot 내에서 읽기 전용으로 기본 파일 시스템을 바인드 마운트하는 것은 어떻습니까?

아마도 읽기 전용 바인드 마운트를 생성하려면 다음과 같아야 합니다.

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

감옥에 쓰기 액세스 권한을 부여하려는 다른 디렉터리를 바인드 마운트할 수 있습니다. 마운트 특수 디렉토리(/dev/, /proc/, /sys/)를 바인드해야 하는 경우 해당 디렉토리를 있는 그대로 마운트하는 것이 안전하지 않을 수 있으므로 주의하십시오.

답변2

작업에 적합한 도구는 Bastian Blank의 f 코드를 fseccomp기반으로 하는 것 같습니다 sync-ignoring. 비교적 작은 파일에 대해 이것을 생각해 냈기 때문에 모든 하위 파일이 쓰기 위해 파일을 열 수 없게 되었습니다.

/*
 * 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;
}

여기에서 파일을 계속 읽을 수 있음을 확인할 수 있습니다.

[jojo@kirk: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
/*

파일 삭제, 파일 이동 또는 열기 이외의 기타 파일 작업을 방지하지는 않지만 이러한 작업을 추가할 수 있습니다.

C 코드를 작성하지 않고 이를 달성하는 도구는 다음과 같습니다.시스템 호출 제한기.

답변3

함수에 대한 대체 함수를 작성하고 LD_PRELOAD를 사용하여 로드하는 것을 고려하시겠습니까 open(…)?

답변4

루트로 초기 설정을 수행하는 것이 실제로 가장 쉬운 방법입니다. 구체적으로,읽기 전용 바인드 마운트에 대한 chroot저항이 가장 적은 길이다.

당신은 그것을 사용할 수 있습니다파일 시스템 바인딩mount --bind루트 없이 읽기 전용 보기를 만드는 대신 . 그러나 chroot와 같은 다른 파일에 대한 액세스를 방지하려면 루트로 작업을 수행해야 합니다.

또 다른 방법은LD_PRELOAD후크 파일이 열리고 라이브러리 쓰기 권한이 거부됩니다. 여기에는 특별한 권한이 필요하지 않습니다. 이는 보안 관점에서 우회할 수 있지만 임의의 네이티브 코드가 아닌 특정 기능만 포함해야 하는 사용 사례에는 적합합니다. 그러나 나는 이것을 달성할 수 있는 기존 라이브러리를 알지 못합니다. 또한 사용되거나 생성된 내용에 대한 읽기 전용 보기로 프로그램을 제한하는 데에도 사용할 수 있습니다 LD_PRELOAD. 기존 라이브러리는 모릅니다.mount --bindbindfs

데비안과 그 파생물에서는 다음을 설정할 수 있습니다.슈루트환경. schroot는 setuid 루트이며 루트로 구성해야 하지만 인증된 모든 사용자가 실행할 수 있습니다.

루트의 협력이 필요하지 않은 한 가지 방법은 가상 머신에서 프로세스를 실행하는 것입니다. KVM 또는 VirtualBox를 설정할 수 있습니다.사용자 모드 리눅스. 약간 무거워서 추가 메모리 소비를 의미하지만 원시 기호 계산 속도에는 큰 영향을 미치지 않습니다.

루트가 되지 않고 프로세스를 "감옥"하는 방법은 무엇입니까?영감을 줄 수도 있습니다.

관련 정보