프로세스가 파일을 쓰지 못하게하는 방법 로컬 인 솔루션을 찾고

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

특정 디렉토리 (예 : 현재 디렉토리)에 파일을 쓰는 경우 보너스 포인트가 여전히 가능합니다.

프로세스 로컬 인 솔루션을 찾고 있는데, 즉 전체 시스템에 대해 AppArmor 또는 SELinux와 같은 것을 구성하거나 루트 권한을 포함하지 않는 솔루션을 찾고 있습니다. 커널 모듈을 설치해야 할 수도 있습니다.

기능을 살펴 보았는데 파일을 만드는 기능이 있다면 훌륭하고 쉬웠을 것입니다. ulimit는이 사용 사례를 다루는 경우 편리한 다른 접근 방식입니다.



답변

빈 chroot를 만든 다음 chroot 내에서 기본 파일 시스템을 읽기 전용으로 바인드 마운트하십시오.

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

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

감옥에 쓰기 권한이있는 다른 디렉토리도 바인드 마운트 할 수 있습니다. 특수 디렉토리 (/ dev /, / proc /, / sys /)를 바인드 마운트해야하는 경우주의하여 마운트하는 것이 안전하지 않을 수 있습니다.


답변

이 작업에 적합한 도구는 Bastian Blank의 f 코드를 fseccomp기반으로 하는 것 같습니다. sync-ignoring이 작은 파일을 생각해 내면 모든 어린이가 파일을 쓰기 위해 파일을 열 수 없습니다.

/*
 * Copyright (C) 2013 Joachim Breitner <mail@joachim-breitner.de>
 *
 * Based on code Copyright (C) 2013 Bastian Blank <waldi@debian.org>
 *
 * 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 코드를 작성하지 않고이를 가능하게하는 도구는 syscall_limiter 입니다.


답변

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


답변

가장 간단한 해결책은 관련 파일 시스템이 읽기 전용으로 마운트 된 상태에서 새 파일 시스템 네임 스페이스를 만든 다음 제한하려는 프로그램을 실행하는 래퍼 프로그램 일 것입니다.

이것은 특정 디렉토리를 서비스에 대한 읽기 전용으로 표시하는 데 systemd사용 ReadOnlyDirectories=하는 작업입니다. 새 네임 스페이스를 만드는 작업을 수행 할 수 있는 unshare명령 도 util-linux있으므로 다음과 같은 작업을 수행 할 수 있습니다.

unshare -m <wrapper>

여기서 wrapper실제 대상 프로그램을 시작하기 전에 필요에 따라 다음 바로 다시 마운트 파일 시스템에있을 것입니다.

유일한 문제는 root새로운 네임 스페이스를 만들어야 한다는 것입니다 …


답변

chroot에서 실행할 수 있으며 특수 버전 /tmp 등을 마운트 합니다. 아마도 systemd 는 도움이되며 특히 systemd-nspawn (1) 이며 원하는 것과 같습니다.


답변

가상 머신은 스크립트가 호스트 시스템에 영향을주지 않고 어디에서나 쓸 수 있으며 실제로 작성하려는 위치를 검사하는 것이 목표 인 것 같습니다.

예를 들어 다음과 같이 Arch Linux를 쉽게 시작할 수 있습니다.

kvm -boot d -m 512 -cdrom archlinux-*.iso

답변

루트로 초기 설정을하는 것이 실제로 가장 쉬운 방법입니다. 특히, 읽기 전용 바인드 마운트의 chroot 는 가장 저항이 적은 경로입니다.

root 일 필요없이 읽기 전용보기를 작성하는 대신 bindfs 를 사용할 수 있습니다 mount --bind. 그러나 chroot와 같은 다른 파일에 액세스하지 못하게하려면 root로 무언가를 수행해야합니다.

또 다른 방법은 LD_PRELOAD파일 열기에 연결하고 쓰기를 거부하는 라이브러리에 대한 것입니다. 특별한 권한이 필요하지 않습니다. 보안 측면에서이 방법은 무시할 수 있지만 임의의 고유 코드가 아닌 특정 기능 만 포함해야하는 사용 사례에 적합합니다. 그러나 이것에 대한 기존 라이브러리는 모르겠습니다. 또는 ;로 LD_PRELOAD작성된 읽기 전용보기로 프로그램을 제한하는 데 사용될 수도 있습니다 . 다시, 나는 기존 도서관을 모른다.mount --bindbindfs

데비안 및 파생 제품에서 schroot 환경을 설정할 수 있습니다. Schroot는 setuid root이며 root로 구성해야하지만 권한이있는 모든 사용자가 실행할 수 있습니다.

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

루트가 아닌 프로세스를 “감옥”하는 방법? 영감을 줄 수 있습니다.