[lxc-devel] [lxd/master] seccomp: improvements
brauner on Github
lxc-bot at linuxcontainers.org
Wed Jul 17 09:10:21 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190717/f3b4e2ae/attachment.bin>
-------------- next part --------------
From c3859c27f4fc711662da1eb05341d6e4d6076fc4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 17 Jul 2019 10:42:20 +0200
Subject: [PATCH 1/2] forksyscall: add and use setnsat()
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/main_forksyscall.go | 58 +++++++++++++----------------------------
1 file changed, 18 insertions(+), 40 deletions(-)
diff --git a/lxd/main_forksyscall.go b/lxd/main_forksyscall.go
index 18cf6bc7c6..2f2c8c0712 100644
--- a/lxd/main_forksyscall.go
+++ b/lxd/main_forksyscall.go
@@ -250,56 +250,34 @@ static void forkmknod()
}
}
-static bool change_creds(int ns_fd, cap_t caps, uid_t nsuid, gid_t nsgid)
-{
- __do_close_prot_errno int fd = -EBADF;
-
- if (prctl(PR_SET_KEEPCAPS, 1))
- return false;
-
- fd = openat(ns_fd, "user", O_RDONLY | O_CLOEXEC);
- if (setns(fd, CLONE_NEWUSER))
- return false;
- close(fd);
-
- fd = openat(ns_fd, "mnt", O_RDONLY | O_CLOEXEC);
- if (setns(fd, CLONE_NEWNS))
- return false;
- close(fd);
-
#ifndef CLONE_NEWCGROUP
#define CLONE_NEWCGROUP 0x02000000
#endif
- fd = openat(ns_fd, "cgroup", O_RDONLY | O_CLOEXEC);
- if (fd < 0) {
- if (errno != ENOENT)
- return false;
- } else {
- if (setns(fd, CLONE_NEWCGROUP) && errno != EINVAL)
- return false;
- close(fd);
- }
+const char *ns_names[] = { "user", "mnt", "pid", "uts", "ipc", "net", "cgroup", NULL };
- fd = openat(ns_fd, "ipc", O_RDONLY | O_CLOEXEC);
- if (setns(fd, CLONE_NEWIPC))
- return false;
- close(fd);
+static bool setnsat(int ns_fd, const char *ns)
+{
+ __do_close_prot_errno int fd = -EBADF;
- fd = openat(ns_fd, "net", O_RDONLY | O_CLOEXEC);
- if (setns(fd, CLONE_NEWNET))
+ fd = openat(ns_fd, ns, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
return false;
- close(fd);
- fd = openat(ns_fd, "pid", O_RDONLY | O_CLOEXEC);
- if (setns(fd, CLONE_NEWPID))
- return false;
- close(fd);
+ return setns(fd, CLONE_NEWUSER) == 0;
+}
+
+static bool change_creds(int ns_fd, cap_t caps, uid_t nsuid, gid_t nsgid)
+{
+ __do_close_prot_errno int fd = -EBADF;
- fd = openat(ns_fd, "uts", O_RDONLY | O_CLOEXEC);
- if (setns(fd, CLONE_NEWUTS))
+ if (prctl(PR_SET_KEEPCAPS, 1))
return false;
- // compiler taking care of fd again now
+
+ for (const char **ns = ns_names; ns && *ns; ns++) {
+ if (!setnsat(ns_fd, *ns))
+ return false;
+ }
if (setegid(nsgid))
return false;
From ded98488fca5fa41cc23ef11fa59974282b7c053 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 17 Jul 2019 11:09:22 +0200
Subject: [PATCH 2/2] seccomp: retrieve fs{g,u}id when handling syscalls
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/container_lxc.go | 2 +-
lxd/main_forksyscall.go | 24 +++++++------
lxd/seccomp.go | 74 +++++++++++++++++++++++++++++------------
3 files changed, 68 insertions(+), 32 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 6f1b5dcfba..98f28fd511 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -7603,7 +7603,7 @@ func (c *containerLXC) InsertSeccompUnixDevice(prefix string, m types.Device, pi
return err
}
- err, uid, gid := taskUidGid(pid)
+ err, uid, gid, _, _ := taskIds(pid)
if err != nil {
return err
}
diff --git a/lxd/main_forksyscall.go b/lxd/main_forksyscall.go
index 2f2c8c0712..1b7f2e35ac 100644
--- a/lxd/main_forksyscall.go
+++ b/lxd/main_forksyscall.go
@@ -126,8 +126,8 @@ static void forkmknod()
mode_t mode = 0;
dev_t dev = 0;
pid_t pid = 0;
- uid_t uid = -1;
- gid_t gid = -1;
+ uid_t fsuid = -1, uid = -1;
+ gid_t fsgid = -1, gid = -1;
struct stat s1, s2;
struct statfs sfs1, sfs2;
cap_t caps;
@@ -140,6 +140,8 @@ static void forkmknod()
target_host = advance_arg(true);
uid = atoi(advance_arg(true));
gid = atoi(advance_arg(true));
+ fsuid = atoi(advance_arg(true));
+ fsgid = atoi(advance_arg(true));
chk_perm_only = atoi(advance_arg(true));
if (*target == '/') {
@@ -198,7 +200,7 @@ static void forkmknod()
_exit(EXIT_FAILURE);
}
- setfsgid(gid);
+ setfsgid(fsgid);
ret = seteuid(uid);
if (ret) {
@@ -206,7 +208,7 @@ static void forkmknod()
_exit(EXIT_FAILURE);
}
- setfsuid(uid);
+ setfsuid(fsuid);
ret = cap_set_proc(caps);
if (ret) {
@@ -267,7 +269,7 @@ static bool setnsat(int ns_fd, const char *ns)
return setns(fd, CLONE_NEWUSER) == 0;
}
-static bool change_creds(int ns_fd, cap_t caps, uid_t nsuid, gid_t nsgid)
+static bool change_creds(int ns_fd, cap_t caps, uid_t nsuid, gid_t nsgid, uid_t nsfsuid, gid_t nsfsgid)
{
__do_close_prot_errno int fd = -EBADF;
@@ -282,12 +284,12 @@ static bool change_creds(int ns_fd, cap_t caps, uid_t nsuid, gid_t nsgid)
if (setegid(nsgid))
return false;
- setfsgid(nsgid);
+ setfsgid(nsfsgid);
if (seteuid(nsuid))
return false;
- setfsuid(nsuid);
+ setfsuid(nsfsuid);
if (cap_set_proc(caps))
return false;
@@ -301,8 +303,8 @@ static void forksetxattr()
int flags = 0;
char *name, *path;
char ns_path[PATH_MAX];
- uid_t nsuid;
- gid_t nsgid;
+ uid_t nsfsuid, nsuid;
+ gid_t nsfsgid, nsgid;
pid_t pid = 0;
cap_t caps;
cap_flag_value_t flag;
@@ -313,6 +315,8 @@ static void forksetxattr()
pid = atoi(advance_arg(true));
nsuid = atoi(advance_arg(true));
nsgid = atoi(advance_arg(true));
+ nsfsuid = atoi(advance_arg(true));
+ nsfsgid = atoi(advance_arg(true));
name = advance_arg(true);
path = advance_arg(true);
flags = atoi(advance_arg(true));
@@ -362,7 +366,7 @@ static void forksetxattr()
_exit(EXIT_FAILURE);
}
} else {
- if (!change_creds(ns_fd, caps, nsuid, nsgid)) {
+ if (!change_creds(ns_fd, caps, nsuid, nsgid, nsfsuid, nsfsgid)) {
fprintf(stderr, "%d", EFAULT);
_exit(EXIT_FAILURE);
}
diff --git a/lxd/seccomp.go b/lxd/seccomp.go
index e0830c7aa1..0f9e1e0ca9 100644
--- a/lxd/seccomp.go
+++ b/lxd/seccomp.go
@@ -788,16 +788,18 @@ func NewSeccompServer(d *Daemon, path string) (*SeccompServer, error) {
return &s, nil
}
-func taskUidGid(pid int) (error, int32, int32) {
+func taskIds(pid int) (error, int32, int32, int32, int32) {
status, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
if err != nil {
- return err, -1, -1
+ return err, -1, -1, -1, -1
}
- reUid := regexp.MustCompile("Uid:\\s*([0-9]*)\\s*([0-9]*)")
- reGid := regexp.MustCompile("Gid:\\s*([0-9]*)\\s*([0-9]*)")
- var gid int32
- var uid int32
+ reUid := regexp.MustCompile("Uid:\\s*([0-9]*)\\s*([0-9]*)\\s*([0-9]*)\\s*([0-9]*)")
+ reGid := regexp.MustCompile("Gid:\\s*([0-9]*)\\s*([0-9]*)\\s*([0-9]*)\\s*([0-9]*)")
+ var gid int32 = -1
+ var uid int32 = -1
+ var fsgid int32 = -1
+ var fsuid int32 = -1
uidFound := false
gidFound := false
for _, line := range strings.Split(string(status), "\n") {
@@ -811,13 +813,24 @@ func taskUidGid(pid int) (error, int32, int32) {
// effective uid
result, err := strconv.Atoi(m[2])
if err != nil {
- return err, -1, -1
+ return err, -1, -1, -1, -1
}
uid = int32(result)
uidFound = true
- continue
}
+
+ if m != nil && len(m) > 4 {
+ // fsuid
+ result, err := strconv.Atoi(m[4])
+ if err != nil {
+ return err, -1, -1, -1, -1
+ }
+
+ fsuid = int32(result)
+ }
+
+ continue
}
if !gidFound {
@@ -826,17 +839,28 @@ func taskUidGid(pid int) (error, int32, int32) {
// effective gid
result, err := strconv.Atoi(m[2])
if err != nil {
- return err, -1, -1
+ return err, -1, -1, -1, -1
}
gid = int32(result)
gidFound = true
- continue
}
+
+ if m != nil && len(m) > 4 {
+ // fsgid
+ result, err := strconv.Atoi(m[4])
+ if err != nil {
+ return err, -1, -1, -1, -1
+ }
+
+ fsgid = int32(result)
+ }
+
+ continue
}
}
- return nil, uid, gid
+ return nil, uid, gid, fsuid, fsgid
}
func CallForkmknod(c container, dev types.Device, requestPID int, permissionsOnly int) int {
@@ -846,7 +870,7 @@ func CallForkmknod(c container, dev types.Device, requestPID int, permissionsOnl
return int(-C.EPERM)
}
- err, uid, gid := taskUidGid(requestPID)
+ err, uid, gid, fsuid, fsgid := taskIds(requestPID)
if err != nil {
return int(-C.EPERM)
}
@@ -868,6 +892,7 @@ func CallForkmknod(c container, dev types.Device, requestPID int, permissionsOnl
"forksyscall", "mknod", dev["pid"], dev["path"],
dev["mode_t"], dev["dev_t"], dev["hostpath"],
fmt.Sprintf("%d", uid), fmt.Sprintf("%d", gid),
+ fmt.Sprintf("%d", fsuid), fmt.Sprintf("%d", fsgid),
fmt.Sprintf("%d", permissionsOnly))
if err != nil {
errno, err := strconv.Atoi(stderr)
@@ -1011,14 +1036,16 @@ func (s *SeccompServer) HandleMknodatSyscall(c container, siov *SeccompIovec) in
}
type SetxattrArgs struct {
- nsuid int
- nsgid int
- size int
- pid int
- path string
- name string
- value []byte
- flags C.int
+ nsuid int
+ nsgid int
+ nsfsuid int
+ nsfsgid int
+ size int
+ pid int
+ path string
+ name string
+ value []byte
+ flags C.int
}
func (s *SeccompServer) HandleSetxattrSyscall(c container, siov *SeccompIovec) int {
@@ -1034,12 +1061,15 @@ func (s *SeccompServer) HandleSetxattrSyscall(c container, siov *SeccompIovec) i
args := SetxattrArgs{}
args.pid = int(siov.req.pid)
- err, uid, gid := taskUidGid(args.pid)
+ err, uid, gid, fsuid, fsgid := taskIds(args.pid)
if err != nil {
return int(-C.EPERM)
}
+
args.nsuid = GetNSUid(uint(uid), args.pid)
args.nsgid = GetNSGid(uint(gid), args.pid)
+ args.nsfsuid = GetNSUid(uint(fsuid), args.pid)
+ args.nsfsgid = GetNSGid(uint(fsgid), args.pid)
// const char *path
cBuf := [unix.PathMax]C.char{}
@@ -1083,6 +1113,8 @@ func (s *SeccompServer) HandleSetxattrSyscall(c container, siov *SeccompIovec) i
fmt.Sprintf("%d", args.pid),
fmt.Sprintf("%d", args.nsuid),
fmt.Sprintf("%d", args.nsgid),
+ fmt.Sprintf("%d", args.nsfsuid),
+ fmt.Sprintf("%d", args.nsfsgid),
args.name,
args.path,
fmt.Sprintf("%d", args.flags),
More information about the lxc-devel
mailing list