参考

rwm —— m 是 mknod 权限

1.说明:

实现一个cgroup来跟踪并强制执行对设备文件的打开和mknod限制。 设备cgroup将设备访问白名单与每个cgroup相关联。 白名单条目具有4个字段。 ‘type’ 是 a (all), c (char), 或 b (block)。 'all’表示适用于所有类型以及所有major和minor数字。 major 和 minor 是整数或全部为*。 访问是r(read),w(write)和 m(mknod)的组合。

根设备 cgroup 以 rwm 开头为“all”。 子设备cgroup获取父设备的副本。 管理员然后可以从白名单中删除设备或添加新条目。 子级cgroup永远不会收到其父级拒绝的设备的访问权限。

mknod —— 创建设备文件权限

我们的linux操作系统跟外部设备(如磁盘、光盘等)的通信都是通过设备文件进行的,应用程序可以打开、关闭、读写这些设备文件,从而对设备进行读写,这种操作就像读写普通的文件一样easy。linux为不同种类的设备文件提供了相同的接口,比如read(),write(),open(),close()。

所以在系统与设备通信之前,系统首先要建立一个设备文件,这个设备文件存放在/dev目录下。其实系统默认情况下就已经生成了很多设备文件,但有时候我们需要自己手动新建一些设备文件,这个时候就会用到像mkdir, mknod这样的命令。

mknod 的标准形式为: mknod DEVNAME {b | c} MAJOR MINOR

  1. DEVNAME是要创建的设备文件名,如果想将设备文件放在一个特定的文件夹下,就需要先用mkdir在dev目录下新建一个目录;如/dev/flash:
  2. b和c 分别表示块设备和字符设备:
    b表示系统从块设备中读取数据的时候,直接从内存的buffer中读取数据,而不经过磁盘;
    c表示字符设备文件与设备传送数据的时候是以字符的形式传送,一次传送一个字符,比如打印机、终端都是以字符的形式传送数据;
  3. MAJOR和MINOR分别表示主设备号和次设备号:
    为了管理设备,系统为每个设备分配一个编号,一个设备号由主设备号和次设备号组成。主设备号标示某一种类的设备,次设备号用来区分同一类型的设备。linux操作系统中为设备文件编号分配了32位无符号整数,其中前12位是主设备号,后20位为次设备号,所以在向系统申请设备文件时主设备号不好超过4095,次设备号不好超过2^20 -1。
mknod命令用于创建字符设备文件和块设备文件
(ls /dev -l 结果显示b开头和c开头的,即标识了块设备和字符设备。)
为了管理设备,所以设备中都有两个设备号:

**主设备号:**为了区分不同类型的设备

**次设备号:**为了区分同一设备下不同子设备

例如 通过ls /dev/null -l ,查看null设备:

crw-rw-rw-  1 root root      1,   3 2017-08-16 15:32 null      //c开头,所以null设备为字符设备,主设备号为1,次设备号为3 
格式 : mknod[选项][文件名称] [文件类型] [主设备号] [次设备号]

选项:
-m:设置权限模式,类似于chmod命令,后面跟以下几个参数:
400 -r-------- 拥有者能够读,其他任何人不能进行任何操作;
644 -rw-r--r-- 拥有者都能够读,但只有拥有者可以编辑;
660 -rw-rw---- 拥有者和组用户都可读和写,其他人不能进行任何操作;
664 -rw-rw-r-- 所有人都可读,但只有拥有者和组用户可编辑;
700 -rwx------ 拥有者能够读、写和执行,其他用户不能任何操作;
744 -rwxr--r-- 所有人都能读,但只有拥有者才能编辑和执行;
755 -rwxr-xr-x 所有人都能读和执行,但只有拥有者才能编辑;
777 -rwxrwxrwx 所有人都能读、写和执行(该设置通常不是好想法)。
-z:设置安全的上下文

实例:

sudo mknod   /dev/console2 c 100 2                 //创建字符设备 /dev/console2,主设备号为100,次设备号为2
sudo mknod -m 660  /dev/console2 c 100 2    //创建字符设备 /dev/console2,并设置权限为660(用户和

Docker容器运行时权限和Linux系统功能

相关Docker参数

--cap-add: Add Linux capabilities
--cap-drop: Drop Linux capabilities
--privileged=false: Give extended privileges to this container
--device=[]: Allows you to run devices inside the container without the --privileged flag.

出于容器之间和容器与宿主机的安全隔离保护,在默认的Docker配置下,Docker容器是没有系统权限的。例如不能在一个Docker容器内,再运行一个Dokcer服务(译者注:或者在容器内修改系统时间)。这是因为在默认情况下,容器内的进程不允许访问任何宿主机上的设备。只有获得设备访问授权的容器,才可以访问所有设备(请参阅关于cgroups设备的文档)。

当容器管理员执行docker run --privileged时,将允许Docker容器访问宿主机上的所有设备,并在AppArmor或SELinux中设置一些配置,使容器内的进程可以与容器外运行的进程几乎一样权限来访问宿主机。(有关运行--privileged参数的更多信息,请访问Docker博客。)

Docker --device 的 rwm 权限设置

如果想限制对特定设备的访问,可以使用--device参数。它允许您指定从容器内访问的一个或多个设备。

$ docker run --device=/dev/snd:/dev/snd ...

开启--device参数后,容器内的进程默认将获得这些设备的readwritemknod权限。您也可以为每个--device参数,附加第三个:rwm选项来覆盖默认的设置:

$ docker run --device=/dev/sda:/dev/xvdc --rm -it ubuntu fdisk  /dev/xvdc

Command (m for help): q
$ docker run --device=/dev/sda:/dev/xvdc:r --rm -it ubuntu fdisk  /dev/xvdc
You will not be able to write the partition table.

Command (m for help): q

$ docker run --device=/dev/sda:/dev/xvdc:w --rm -it ubuntu fdisk  /dev/xvdc
    crash....

$ docker run --device=/dev/sda:/dev/xvdc:m --rm -it ubuntu fdisk  /dev/xvdc
fdisk: unable to open /dev/xvdc: Operation not permitted

除了 --privileged之外,操作员还可以使用--cap-add--cap-drop对功能进行细粒度控制。默认情况下,Docker有一个保留的默认功能列表。

下表列出了Linux功能选项,这些选项是默认允许的,可以删除。

功能项功能描述
SETPCAP修改进程的权限
MKNOD使用mknod(2)创建特殊文件
AUDIT_WRITE将记录写入内核审计日志
CHOWN任意更改文件UIDs和GIDs(见chown(2))
NET_RAW使用 RAW 和 PACKET 套接字
DAC_OVERRIDE绕过文件的读、写和执行权限检查
FOWNER绕过对进程的文件系统UID与文件的UID进行权限匹配的检查操作
FSETID当文件被修改时,不要清除set-user-ID和set-group-ID权限位
KILL绕过发送信号的权限检查
SETGID自定义处理进程GID和补充GID列表
SETUID自定义处理进程UID
NET_BIND_SERVICE将套接字绑定到互联网域名专用端口(端口号小于1024)。
SYS_CHROOT使用chroot(2),更改根目录
SETFCAP设置文件功能

下表显示了默认情况下未授予的功能,可以手动添加这些功能。

功能项功能描述
SYS_MODULE加载和卸载内核模块
SYS_RAWIO执行I / O端口操作(iopl(2)和ioperm(2))
SYS_PACCT使用acct(2),打开或关闭进程计数
SYS_ADMIN执行一系列系统管理操作
SYS_NICE提高进程的nice值(nice(2),setpriority(2))并更改任意进程的nice值
SYS_RESOURCE覆盖资源限制
SYS_TIME设置系统时钟(settimeofday(2),stime(2),adjtimex(2)); 设置实时(硬件)时钟
SYS_TTY_CONFIG使用vhangup(2); 在虚拟终端上使用各种特权的ioctl(2)操作
AUDIT_CONTROL启用和禁用内核审核; 更改审核过滤器规则; 检索审核状态和过滤规则
MAC_ADMIN允许MAC配置或状态更改。 为Smack LSM而实现的功能
MAC_OVERRIDE覆盖强制访问控制(MAC)。 为Smack Linux安全模块(LSM)实现
NET_ADMIN执行各种与网络相关的操作
SYSLOG执行syslog(2)的权限操作。
DAC_READ_SEARCH绕过文件读取权限检查以及目录读取和执行权限检查
LINUX_IMMUTABLE设置FS_APPEND_FL和FS_IMMUTABLE_FL i-node 标志
NET_BROADCAST使套接字可以实现广播,并监听广播包
IPC_LOCK锁定内存(mlock(2),mlockall(2),mmap(2),shmctl(2))
IPC_OWNER绕过对System V IPC对象操作的权限检查
SYS_PTRACE使用ptrace(2)跟踪任意进程
SYS_BOOT使用reboot(2)和kexec_load(2),重新引导并加载新内核以供程序执行
LEASE在任意文件上建立Lease租约(请参阅fcntl(2))
WAKE_ALARM触发唤醒系统的操作
BLOCK_SUSPEND开启可以阻止系统挂起的功能

更多的参考信息可以在 capabilities(7) - Linux man page Linux手册页中找到

--cap-add --cap-drop两个参数都支持值ALL,所以如果Docker管理员想要获得除了MKNOD以外的所有Linux功能,可以使用:

$ docker run --cap-add=ALL --cap-drop=MKNOD ...

如果想与系统的网络堆栈进行交互,应该使用--cap-add=NET_ADMIN来修改网络接口,而不是使用--privileged

$ docker run -it --rm  ubuntu:14.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
$ docker run -it --rm --cap-add=NET_ADMIN ubuntu:14.04 ip link add dummy0 type dummy

要安装一个基于FUSE的文件系统,您需要结合--cap-add--device:

$ docker run --rm -it --cap-add SYS_ADMIN sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fuse: failed to open /dev/fuse: Operation not permitted
$ docker run --rm -it --device /dev/fuse sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fusermount: mount failed: Operation not permitted
$ docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse sshfs
# sshfs sven@10.10.10.20:/home/sven /mnt
The authenticity of host '10.10.10.20 (10.10.10.20)' can't be established.
ECDSA key fingerprint is 25:34:85:75:25:b0:17:46:05:19:04:93:b5:dd:5f:c6.
Are you sure you want to continue connecting (yes/no)? yes
sven@10.10.10.20's password:
root@30aa0cfaf1b5:/# ls -la /mnt/src/docker
total 1516
drwxrwxr-x 1 1000 1000   4096 Dec  4 06:08 .
drwxrwxr-x 1 1000 1000   4096 Dec  4 11:46 ..
-rw-rw-r-- 1 1000 1000     16 Oct  8 00:09 .dockerignore
-rwxrwxr-x 1 1000 1000    464 Oct  8 00:09 .drone.yml
drwxrwxr-x 1 1000 1000   4096 Dec  4 06:11 .git
-rw-rw-r-- 1 1000 1000    461 Dec  4 06:08 .gitignore
....

默认的seccomp配置文件将根据所选的功能进行调整,以允许使用功能所允许的功能,所以从Docker1.12之后的版本,不应该对此进行调整。在Docker 1.10和1.11中没有这种情况,在添加功能时可能需要使用一个自定义的seccomp配置文件或使用--security-opt seccomp=unconfined

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐