Browse Source

Make our seccomp2 sandbox handle Glibc 2.26

There are three changes here:
  * We need to allow epoll_pwait.
  * We need to allow PF_NETLINK sockets to be opened with SOCK_CLOEXEC.
  * We need to use openat() instead of open().

Note that this fix is not complete, since the openat() change is
turned off.  The next commit will make the openat() change happen
when we're running glibc 2.26 or later.

Fix for 24315.
Nick Mathewson 6 years ago
parent
commit
d2d6a1b082
1 changed files with 31 additions and 4 deletions
  1. 31 4
      src/common/sandbox.c

+ 31 - 4
src/common/sandbox.c

@@ -127,6 +127,9 @@ static int filter_nopar_gen[] = {
     SCMP_SYS(clone),
     SCMP_SYS(epoll_create),
     SCMP_SYS(epoll_wait),
+#ifdef __NR_epoll_pwait
+    SCMP_SYS(epoll_pwait),
+#endif
 #ifdef HAVE_EVENTFD
     SCMP_SYS(eventfd2),
 #endif
@@ -421,6 +424,21 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 }
 #endif
 
+/** Allow a single file to be opened.  If <b>use_openat</b> is true,
+ * we're using a libc that remaps all the opens into openats. */
+static int
+allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
+{
+  if (use_openat) {
+    return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
+                              SCMP_CMP_STR(0, SCMP_CMP_EQ, AT_FDCWD),
+                              SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
+  } else {
+    return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
+                              SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
+  }
+}
+
 /**
  * Function responsible for setting up the open syscall for
  * the seccomp filter sandbox.
@@ -437,8 +455,7 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
     if (param != NULL && param->prot == 1 && param->syscall
         == SCMP_SYS(open)) {
-      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
-            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
+      rc = allow_file_open(ctx, 0 /* XXXX */, param->value);
       if (rc != 0) {
         log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
             "libseccomp error %d", rc);
@@ -456,6 +473,15 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
     return rc;
   }
 
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(openat),
+                SCMP_CMP_MASKED(2, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW,
+                                O_RDONLY));
+  if (rc != 0) {
+    log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
+            "libseccomp error %d", rc);
+    return rc;
+  }
+
   return 0;
 }
 
@@ -645,7 +671,7 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
   rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
       SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
-      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW),
+      SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
       SCMP_CMP(2, SCMP_CMP_EQ, 0));
   if (rc)
     return rc;
@@ -1616,7 +1642,8 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
 
   // function pointer
   for (i = 0; i < ARRAY_LENGTH(filter_func); i++) {
-    if ((filter_func[i])(ctx, cfg)) {
+    rc = filter_func[i](ctx, cfg);
+    if (rc) {
       log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp "
           "error %d", i, rc);
       return rc;