| 
					
				 | 
			
			
				@@ -62,6 +62,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <time.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <poll.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef HAVE_GNU_LIBC_VERSION_H 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <gnu/libc-version.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #ifdef HAVE_LINUX_NETFILTER_IPV4_H 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <linux/netfilter_ipv4.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -133,6 +136,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 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -397,6 +403,52 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif /* defined(__NR_mmap2) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef HAVE_GNU_LIBC_VERSION_H 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef HAVE_GNU_GET_LIBC_VERSION 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define CHECK_LIBC_VERSION 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Return true if we think we're running with a libc that always uses 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * openat on linux. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+libc_uses_openat_for_everything(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef CHECK_LIBC_VERSION 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const char *version = gnu_get_libc_version(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (version == NULL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int major = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int minor = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_sscanf(version, "%d.%d", &major, &minor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (major >= 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else if (major == 2 && minor >= 26) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#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. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -407,14 +459,15 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int rc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sandbox_cfg_t *elem = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int use_openat = libc_uses_openat_for_everything(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // for each dynamic parameter filters 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (elem = filter; elem != NULL; elem = elem->next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     smp_param_t *param = elem->param; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     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, use_openat, param->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (rc != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "libseccomp error %d", rc); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -432,6 +485,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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -621,7 +683,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; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1054,6 +1116,19 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif /* defined(__NR_stat64) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (void) filter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef __NR_kill 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Allow killing anything with signal 0 -- it isn't really a kill. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       SCMP_CMP(1, SCMP_CMP_EQ, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * Array of function pointers responsible for filtering different syscalls at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * a parameter level. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1090,10 +1165,10 @@ static sandbox_filter_func_t filter_func[] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sb_setsockopt, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sb_getsockopt, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sb_socketpair, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #ifdef HAVE_KIST_SUPPORT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sb_ioctl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sb_kill 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const char * 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1601,7 +1676,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; 
			 |