Example #1
0
int main(int argc, char *argv[]) {

    if (argc < 6 || strcmp(argv[1], "--error") || (strcmp(argv[3], "--allow") && strcmp(argv[3], "--deny"))) {
        usage(argv[0]);
        return 1;
    }

    const int err = parse_positive(argv[2]);
    if (err < 0) {
        return 2;
    }
    const bool default_block = !strcmp(argv[3], "--allow");

    if (-1 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl");
        return 10;
    }

    uint32_t rule_action = !default_block ? SCMP_ACT_ERRNO(err) : SCMP_ACT_ALLOW;
    scmp_filter_ctx ctx = seccomp_init(default_block ? SCMP_ACT_ERRNO(err) : SCMP_ACT_ALLOW);

    int arg = 4;
    for (; arg < argc; ++arg) {
        if (!strcmp(argv[arg], "--")) {
            ++arg;
            break;
        }

        const int syscall_no = parse_positive(argv[arg]);

        if (syscall_no < 0) {
            seccomp_release(ctx);
            return 5;
        }

        if (seccomp_rule_add(ctx, rule_action, syscall_no, 0)) {
            perror("rule add");
            fprintf(stderr, "not a valid syscall number for a rule: '%s'\n", argv[arg]);
            seccomp_release(ctx);
            return 20;
        }
    }

    if (arg == argc) {
        usage(argv[0]);
        return 3;
    }

    if (seccomp_load(ctx)) {
        perror("load");
        seccomp_release(ctx);
        return 4;
    }

    seccomp_release(ctx);
    execvp(argv[arg], &argv[arg]);
    perror("execve");
    return 5;
}
Example #2
0
/**
 * Function responsible for setting up the open syscall for
 * the seccomp filter sandbox.
 */
static int
sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  sandbox_cfg_t *elem = NULL;

  // 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));
      if (rc != 0) {
        log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
            "libseccomp error %d", rc);
        return rc;
      }
    }
  }

  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open),
                SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW,
                                O_RDONLY));
  if (rc != 0) {
    log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp "
        "error %d", rc);
    return rc;
  }

  return 0;
}
Example #3
0
static int seccomp_add_default_syscall_filter(scmp_filter_ctx ctx,
                                              uint64_t cap_list_retain) {
        unsigned i;
        int r;
        static const struct {
                uint64_t capability;
                int syscall_num;
        } blacklist[] = {
                { CAP_SYS_RAWIO,  SCMP_SYS(iopl)              },
                { CAP_SYS_RAWIO,  SCMP_SYS(ioperm)            },
                { CAP_SYS_BOOT,   SCMP_SYS(kexec_load)        },
                { CAP_SYS_ADMIN,  SCMP_SYS(swapon)            },
                { CAP_SYS_ADMIN,  SCMP_SYS(swapoff)           },
                { CAP_SYS_ADMIN,  SCMP_SYS(open_by_handle_at) },
                { CAP_SYS_MODULE, SCMP_SYS(init_module)       },
                { CAP_SYS_MODULE, SCMP_SYS(finit_module)      },
                { CAP_SYS_MODULE, SCMP_SYS(delete_module)     },
                { CAP_SYSLOG,     SCMP_SYS(syslog)            },
        };

        for (i = 0; i < ELEMENTSOF(blacklist); i++) {
                if (cap_list_retain & (1ULL << blacklist[i].capability))
                        continue;

                r = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0);
                if (r == -EFAULT)
                        continue; /* unknown syscall */
                if (r < 0) {
                        log_error_errno(r, "Failed to block syscall: %m");
                        return r;
                }
        }

        return 0;
}
Example #4
0
void sandboxify() {
	if (seccomp_init(SCMP_ACT_TRAP) < 0)
		ERROR("Cannot go into SECCOMPv2");

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); // XXXX

	// seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(open), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(access), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fcntl), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fstat), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fstat64), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(stat64), 0);

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(getdents), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(dup), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); // XXXX

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(getdents64), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	// seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); // XXX
	// seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); // XXX
	// seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); // XXX

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0);

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(time), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

#ifdef DEBUG_SECCOMP
	if (install_syscall_reporter())
		ERROR("Cannot install syscall reporter");
#endif

	if (seccomp_load() < 0)
		ERROR("Cannot load SECCOMP filters");

	seccomp_release();
}
Example #5
0
int lxc_read_seccomp_config(struct lxc_conf *conf)
{
	FILE *f;
	int ret;

	if (!conf->seccomp)
		return 0;

#if HAVE_SCMP_FILTER_CTX
	/* XXX for debug, pass in SCMP_ACT_TRAP */
	conf->seccomp_ctx = seccomp_init(SCMP_ACT_ERRNO(31));
	ret = !conf->seccomp_ctx;
#else
	ret = seccomp_init(SCMP_ACT_ERRNO(31)) < 0;
#endif
	if (ret) {
		ERROR("failed initializing seccomp");
		return -1;
	}

	/* turn of no-new-privs.  We don't want it in lxc, and it breaks
	 * with apparmor */
	if (seccomp_attr_set(
#if HAVE_SCMP_FILTER_CTX
			conf->seccomp_ctx,
#endif
			SCMP_FLTATR_CTL_NNP, 0)) {
		ERROR("failed to turn off n-new-privs\n");
		return -1;
	}

	process_lock();
	f = fopen(conf->seccomp, "r");
	process_unlock();
	if (!f) {
		SYSERROR("failed to open seccomp policy file %s\n", conf->seccomp);
		return -1;
	}
	ret = parse_config(f, conf);
	process_lock();
	fclose(f);
	process_unlock();
	return ret;
}
u_int32_t pcm_string_to_policy(const char *str)
{
	if(strcasecmp(str, "ALLOW") == 0) {
		return SCMP_ACT_ALLOW;
	} else if(strcasecmp(str, "KILL") == 0) {
		return SCMP_ACT_KILL;
	} else if(strcasecmp(str, "ERRNO") == 0) {
		return SCMP_ACT_ERRNO(EPERM);
	} 

	return -1;
}
Example #7
0
static int
sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  (void) filter;
  (void) ctx;

  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(_sysctl));
  if (rc != 0) {
    log_err(LD_BUG,"(Sandbox) failed to add _sysctl syscall, "
        "received libseccomp error %d", rc);
    return rc;
  }

  return 0;
}
Example #8
0
bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx,
			uint32_t action)
{
	int nr, ret;

	ret = seccomp_arch_exist(ctx, arch);
	if (arch && ret != 0) {
		ERROR("BUG: Seccomp: rule and context arch do not match (arch "
		      "%d): %s.",
		      arch, strerror(-ret));
		return false;
	}

	if (strncmp(line, "reject_force_umount", 19) == 0) {
		INFO("Setting Seccomp rule to reject force umounts.");
		ret = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(umount2),
				1, SCMP_A1(SCMP_CMP_MASKED_EQ , MNT_FORCE , MNT_FORCE ));
		if (ret < 0) {
			ERROR("Failed (%d) loading rule to reject force "
			      "umount: %s.",
			      ret, strerror(-ret));
			return false;
		}
		return true;
	}

	nr = seccomp_syscall_resolve_name(line);
	if (nr == __NR_SCMP_ERROR) {
		WARN("Seccomp: failed to resolve syscall: %s.", line);
		WARN("This syscall will NOT be blacklisted.");
		return true;
	}
	if (nr < 0) {
		WARN("Seccomp: got negative for syscall: %d: %s.", nr, line);
		WARN("This syscall will NOT be blacklisted.");
		return true;
	}
	ret = seccomp_rule_add_exact(ctx, action, nr, 0);
	if (ret < 0) {
		ERROR("Failed (%d) loading rule for %s (nr %d action %d): %s.",
		      ret, line, nr, action, strerror(-ret));
		return false;
	}
	return true;
}
Example #9
0
static uint32_t get_v2_default_action(char *line)
{
	uint32_t ret_action = -1;

	while (*line == ' ') line++;
	// after 'whitelist' or 'blacklist' comes default behavior
	if (strncmp(line, "kill", 4) == 0)
		ret_action = SCMP_ACT_KILL;
	else if (strncmp(line, "errno", 5) == 0) {
		int e;
		if (sscanf(line+5, "%d", &e) != 1) {
			ERROR("Bad errno value in %s", line);
			return -2;
		}
		ret_action = SCMP_ACT_ERRNO(e);
	} else if (strncmp(line, "allow", 5) == 0)
		ret_action = SCMP_ACT_ALLOW;
	else if (strncmp(line, "trap", 4) == 0)
		ret_action = SCMP_ACT_TRAP;
	return ret_action;
}
Example #10
0
int main(int argc, char* argv[], char* envp[]) {
    
    if (argc<3 || !strcmp(argv[1], "-?") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "--version")) {
        fprintf(stderr, "Usage: limit_syscalls syscall1 syscall2 ... syscallN -- program [arguments]\n");
        fprintf(stderr, "Example:\n"
            "   limit_syscalls execve exit write read open close mmap2  fstat64 access  mprotect set_thread_area -- /bin/echo qqq\n");
        fprintf(stderr, "Advanced:\n");
        fprintf(stderr, "   LIMIT_SYSCALLS_DEFAULT_ACTION={a,k,eN} - by default allow, kill or return error N\n");
        fprintf(stderr, "   some_syscall,A0>=3,A4<<1000,A1!=4,A2&&0x0F==0x0F - compare arguments\n");
        fprintf(stderr, "   some_syscall,{a,k,eN} - allow, kill or return error N for this rule\n");
        fprintf(stderr, "Some more example:\n");
        fprintf(stderr,"    LIMIT_SYSCALLS_DEFAULT_ACTION=a  limit_syscalls  'write,A0==1,e0' -- /usr/bin/printf --help\n");
        fprintf(stderr,"     (this makes write to stdout in /usr/bin/printf silently fail, looping it)\n");
        return 126;
    }
    
    // ECHRNG, just to provide more or less noticable message when we block a syscall
    uint32_t default_action = SCMP_ACT_ERRNO(44);
    
    if (getenv("LIMIT_SYSCALLS_DEFAULT_ACTION")) {
        const char* e = getenv("LIMIT_SYSCALLS_DEFAULT_ACTION");
        if(!strcmp(e, "a")) default_action=SCMP_ACT_ALLOW;
        else 
        if(!strcmp(e, "k")) default_action=SCMP_ACT_KILL;
        else
        if(e[0] == 'e') {
            int errno_;
            if (sscanf(e+1,"%i", &errno_)!=1) {
                fprintf(stderr, "LIMIT_SYSCALLS_DEFAULT_ACTION=e<number> expected\n");
                return 109;
            }
            default_action=SCMP_ACT_ERRNO(errno_);
        }
        else
        {
            fprintf(stderr, "LIMIT_SYSCALLS_DEFAULT_ACTION should be a, k or e<number>\n");
            return 110;
        } 
    }
    
    scmp_filter_ctx ctx = seccomp_init(default_action);
    if (!ctx) {
        perror("seccomp_init");
        return 126;
    }
    
    int i;
    
    for (i=1; i<argc; ++i) {
        if (!strcmp(argv[i], "--")) break;
            
        const char* syscall_name = strtok(argv[i], ",");
                
        int syscall = seccomp_syscall_resolve_name(argv[i]);
        
        if (syscall == __NR_SCMP_ERROR) {
            fprintf(stderr, "Failed to resolve syscall %s\n", syscall_name);
            return 125;
        }
        
        int nargs = 0;
        struct scmp_arg_cmp args[6];
        
        uint32_t action = SCMP_ACT_ALLOW;
        
        const char* aa = strtok(NULL, ",");
        for (;aa; aa=strtok(NULL, ",")) {
            if (aa[0]=='A') {
                if(nargs==6) {
                    fprintf(stderr, "Maximum comparator count (6) exceed in %s\n", argv[i]);
                    return 103;
                }
                if( !(aa[1]>='0' && aa[1]<='5') ) {
                    fprintf(stderr, "A[0-5] expected in %s\n", argv[i]);
                    return 100;
                }
                int cmp = 0; /* invalid value */
                
                if(!strncmp(aa+2, "!=", 2)) cmp=SCMP_CMP_NE;
                if(!strncmp(aa+2, "<<", 2)) cmp=SCMP_CMP_LT;
                if(!strncmp(aa+2, "<=", 2)) cmp=SCMP_CMP_LE;
                if(!strncmp(aa+2, "==", 2)) cmp=SCMP_CMP_EQ;
                if(!strncmp(aa+2, ">=", 2)) cmp=SCMP_CMP_GE;
                if(!strncmp(aa+2, ">>", 2)) cmp=SCMP_CMP_GT;
                if(!strncmp(aa+2, "&&", 2)) cmp=SCMP_CMP_MASKED_EQ;
                    
                if (!cmp) {
                    fprintf(stderr, "After An there should be comparison operator like"
                        " != << <= == => >> ot &&; in %s\n", argv[i]);
                    return 101;
                }
                
                if (cmp != SCMP_CMP_MASKED_EQ) {
                    scmp_datum_t datum;
                    if(sscanf(aa+4, "%lli", &datum)!=1) {
                        fprintf(stderr, "After AxOP there should be some sort of number in %s\n", argv[i]);
                        return 102;
                    }
                    
                    args[nargs++] = SCMP_CMP(aa[1]-'0', cmp, datum);
                } else {
                    scmp_datum_t mask;
                    scmp_datum_t datum;
                    if(sscanf(aa+4, "%lli==%lli", &mask, &datum)!=2) {
                        fprintf(stderr, "After Ax&& there should be number==number; in %s\n", argv[i]);
                        return 104;
                    }
                    
                    args[nargs++] = SCMP_CMP(aa[1]-'0', SCMP_CMP_MASKED_EQ, mask, datum);
                }
            } else
            if (aa[0]=='e') {
                int errno_;
                if (sscanf(aa+1,"%i", &errno_)!=1) {
                    fprintf(stderr, "After e should be number in %s\n", argv[i]);
                    return 105;
                }
                
                action = SCMP_ACT_ERRNO(errno_);
            } else
            if (aa[0]=='k') {
                action = SCMP_ACT_KILL;
            } else
            if (aa[0]=='a') {
                action = SCMP_ACT_ALLOW;
            } else {
                fprintf(stderr, "Unknown %c in %s\n", aa[0], argv[i]);
                return 107;
            }
        }
        
        int ret = seccomp_rule_add_hack(ctx, action, syscall, nargs, args);
        
        if (ret!=0) {
            fprintf(stderr, "seccomp_rule_add returned %d\n", ret);
            return 124;
        }
    }
    
    int ret = seccomp_load(ctx);
    if (ret!=0) {
        fprintf(stderr, "seccomp_load returned %d\n", ret);        
    }
    
    execve(argv[i+1], argv+i+1, envp);
    
    perror("execve");    
    return 123;
}
Example #11
0
int main(int argc, char *argv[])
{
	int opt = 0;
	bool autoall = FALSE;
	int configsetup = 0;
	int checkconfig = 0;
	const char *export = "export"; /* display export before the foo=bar or not */
	bool
		dolist = FALSE,
		listadd = FALSE,
		listroute = FALSE,
		liststart = FALSE,
		listignore = FALSE,
		listall = FALSE,
		liststack = FALSE;
	char *configfile = NULL;
	const char *varprefix = "";
	int exit_status = 0;
	struct starter_conn *conn = NULL;
	const char *ctlbase = NULL;
	bool resolvip = TRUE; /* default to looking up names */

#if 0
	/* efence settings */
	extern int EF_PROTECT_BELOW;
	extern int EF_PROTECT_FREE;

	EF_PROTECT_BELOW = 1;
	EF_PROTECT_FREE = 1;
#endif

	progname = argv[0];
	rootdir[0] = '\0';

	tool_init_log();

	while ((opt = getopt_long(argc, argv, "", longopts, 0)) != EOF) {
		switch (opt) {
		case 'h':
			/* usage: */
			usage();
			break;

		case 'a':
			autoall = TRUE;
			break;

		case 'D':
			verbose++;
			lex_verbosity++;
			break;

		case 'T':
			configsetup++;	/* ??? is this not idempotent? */
			break;

		case 'K':
			checkconfig++;	/* ??? is this not idempotent? */
			break;

		case 'N':
			export = "";
			break;

		case 'C':
			configfile = clone_str(optarg, "config file name");
			break;

		case 'c':
			ctlbase = clone_str(optarg, "control base");
			break;

		case 'L':
			listadd = TRUE;
			dolist = TRUE;
			break;

		case 'r':
			listroute = TRUE;
			dolist = TRUE;
			break;

		case 's':
			liststart = TRUE;
			dolist = TRUE;
			break;

		case 'S':
			liststack = TRUE;
			dolist = TRUE;
			break;

		case 'i':
			listignore = TRUE;
			dolist = TRUE;
			break;

		case 'A':
			listall = TRUE;
			dolist = TRUE;
			break;

		case 'P':
			varprefix = optarg;
			break;

		case 'R':
			printf("setting rootdir=%s\n", optarg);
			jam_str(rootdir, sizeof(rootdir), optarg);
			break;

		case 'd':
		case 'n':
			printf("Warning: options --defaultroute and --defaultroutenexthop are obsolete and were ignored\n");
			break;

		default:
			usage();
		}
	}

	/* if nothing to add, then complain */
	if (optind == argc && !autoall && !dolist && !configsetup &&
		!checkconfig)
		usage();

	if (verbose > 3) {
		yydebug = 1;
	}

	char *confdir = IPSEC_CONFDIR;

	if (configfile == NULL) {
		/* ??? see code clone in programs/readwriteconf/readwriteconf.c */
		configfile = alloc_bytes(strlen(confdir) +
					 sizeof("/ipsec.conf"),
					 "conf file");

		/* calculate default value for configfile */
		strcpy(configfile, confdir);	/* safe: see allocation above */
		if (configfile[0] != '\0' && configfile[strlen(configfile) - 1] != '/')
			strcat(configfile, "/");	/* safe: see allocation above */
		strcat(configfile, "ipsec.conf");	/* safe: see allocation above */
	}

	if (verbose)
		printf("opening file: %s\n", configfile);

	starter_use_log(verbose != 0, TRUE, verbose == 0);

	if (configsetup || checkconfig || dolist) {
		/* skip if we have no use for them... causes delays */
		resolvip = FALSE;
	}

	struct starter_config *cfg = NULL;

	{
		err_t err = NULL;

		cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup);

		if (cfg == NULL) {
			fprintf(stderr, "cannot load config '%s': %s\n",
				configfile, err);
			exit(3);
		} else if (checkconfig) {
			confread_free(cfg);
			exit(0);
		}
	}

#ifdef HAVE_SECCOMP
	switch(cfg->setup.options[KBF_SECCOMP]) {
		case SECCOMP_ENABLED:
		init_seccomp_addconn(SCMP_ACT_KILL);
		break;
	case SECCOMP_TOLERANT:
		init_seccomp_addconn(SCMP_ACT_ERRNO(EACCES));
		break;
	case SECCOMP_DISABLED:
		break;
	default:
		bad_case(cfg->setup.options[KBF_SECCOMP]);
	}
#endif

	if (autoall) {
		if (verbose)
			printf("loading all conns according to their auto= settings\n");

		/*
		 * Load all conns marked as auto=add or better.
		 * First, do the auto=route and auto=add conns to quickly
		 * get routes in place, then do auto=start as these can be
		 * slower.
		 * This mimics behaviour of the old _plutoload
		 */
		if (verbose)
			printf("  Pass #1: Loading auto=add, auto=route and auto=start connections\n");

		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next) {
			if (conn->desired_state == STARTUP_ADD ||
				conn->desired_state == STARTUP_ONDEMAND ||
				conn->desired_state == STARTUP_START) {
				if (verbose)
					printf(" %s", conn->name);
				resolve_defaultroute(conn);
				starter_whack_add_conn(cfg, conn);
			}
		}

		/*
		 * We loaded all connections. Now tell pluto to listen,
		 * then route the conns and resolve default route.
		 */
		starter_whack_listen(cfg);

		if (verbose)
			printf("  Pass #2: Routing auto=route and auto=start connections\n");

		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next) {
			if (conn->desired_state == STARTUP_ADD ||
				conn->desired_state == STARTUP_ONDEMAND ||
				conn->desired_state == STARTUP_START) {
				if (verbose)
					printf(" %s", conn->name);
				resolve_defaultroute(conn);
				if (conn->desired_state == STARTUP_ONDEMAND ||
				    conn->desired_state == STARTUP_START) {
					starter_whack_route_conn(cfg, conn);
				}
			}
		}

		if (verbose)
			printf("  Pass #3: Initiating auto=start connections\n");

		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next) {
			if (conn->desired_state == STARTUP_START) {
				if (verbose)
					printf(" %s", conn->name);
				starter_whack_initiate_conn(cfg, conn);
			}
		}

		if (verbose)
			printf("\n");
	} else {
		/* load named conns, regardless of their state */
		int connum;

		if (verbose)
			printf("loading named conns:");
		for (connum = optind; connum < argc; connum++) {
			char *connname = argv[connum];

			if (verbose)
				printf(" %s", connname);
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (streq(conn->name, connname)) {
					if (conn->state == STATE_ADDED) {
						printf("\nconn %s already added\n",
							conn->name);
					} else if (conn->state ==
						STATE_FAILED) {
						printf("\nconn %s did not load properly\n",
							conn->name);
					} else {
						resolve_defaultroute(conn);
						exit_status =
							starter_whack_add_conn(
								cfg,
								conn);
						conn->state = STATE_ADDED;
					}
					break;
				}
			}

			if (conn == NULL) {
				/*
				 * only if we don't find it, do we now look
				 * for aliases
				 */
				for (conn = cfg->conns.tqh_first;
					conn != NULL;
					conn = conn->link.tqe_next) {
					if (conn->strings_set[KSCF_CONNALIAS] &&
						lsw_alias_cmp(connname,
							conn->
							strings[KSCF_CONNALIAS]
							)) {
						if (conn->state ==
							STATE_ADDED) {
							printf("\nalias: %s conn %s already added\n",
								connname,
								conn->name);
						} else if (conn->state ==
							STATE_FAILED) {
							printf("\nalias: %s conn %s did not load properly\n",
								connname,
								conn->name);
						} else {
							resolve_defaultroute(
								conn);
							exit_status =
								starter_whack_add_conn(
									cfg,
									conn);
							conn->state =
								STATE_ADDED;
						}
						break;
					}
				}
			}

			if (conn == NULL) {
				exit_status++;
				if (!verbose) {
					printf("conn '%s': not found (tried aliases)\n",
						connname);
				} else {
					printf(" (notfound)\n");
				}
			}
		}
	}

	if (listall) {
		if (verbose)
			printf("listing all conns\n");
		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next)
			printf("%s ", conn->name);
		printf("\n");
	} else {
		if (listadd) {
			if (verbose)
				printf("listing all conns marked as auto=add\n");

			/* list all conns marked as auto=add */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_ADD)
					printf("%s ", conn->name);
			}
		}
		if (listroute) {
			if (verbose)
				printf("listing all conns marked as auto=route and auto=start\n");

			/*
			 * list all conns marked as auto=route or start or
			 * better
			 */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_START ||
					conn->desired_state == STARTUP_ONDEMAND)
					printf("%s ", conn->name);
			}
		}

		if (liststart && !listroute) {
			if (verbose)
				printf("listing all conns marked as auto=start\n");

			/* list all conns marked as auto=start */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_START)
					printf("%s ", conn->name);
			}
		}

		if (listignore) {
			if (verbose)
				printf("listing all conns marked as auto=ignore\n");

			/* list all conns marked as auto=start */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_IGNORE)
					printf("%s ", conn->name);
			}
			printf("\n");
		}
	}

	if (liststack) {
		const struct keyword_def *kd;

		for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) {
			if (strstr(kd->keyname, "protostack")) {
				if (cfg->setup.strings[kd->field]) {
					printf("%s\n",
						cfg->setup.strings[kd->field]);
				} else {
					/* implicit default */
					printf("netkey\n");
				}
			}
		}
		confread_free(cfg);
		exit(0);
	}

	if (configsetup) {
		const struct keyword_def *kd;

		printf("%s %sconfreadstatus=''\n", export, varprefix);
		for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) {
			if ((kd->validity & kv_config) == 0)
				continue;

			switch (kd->type) {
			case kt_string:
			case kt_filename:
			case kt_dirname:
			case kt_loose_enum:
				if (cfg->setup.strings[kd->field]) {
					printf("%s %s%s='%s'\n",
						export, varprefix, kd->keyname,
						cfg->setup.strings[kd->field]);
				}
				break;

			case kt_bool:
				printf("%s %s%s='%s'\n", export, varprefix,
					kd->keyname,
					cfg->setup.options[kd->field] ?
					"yes" : "no");
				break;

			case kt_list:
				printf("%s %s%s='",
					export, varprefix, kd->keyname);
				confwrite_list(stdout, "",
					cfg->setup.options[kd->field],
					kd);
				printf("'\n");
				break;

			case kt_obsolete:
				printf("# obsolete option '%s%s' ignored\n",
					varprefix, kd->keyname);
				break;

			default:
				if (cfg->setup.options[kd->field] ||
					cfg->setup.options_set[kd->field]) {
					printf("%s %s%s='%d'\n",
						export, varprefix, kd->keyname,
						cfg->setup.options[kd->field]);
				}
				break;
			}
		}
Example #12
0
int setup_seccomp(uint64_t cap_list_retain) {
        scmp_filter_ctx seccomp;
        int r;

        seccomp = seccomp_init(SCMP_ACT_ALLOW);
        if (!seccomp)
                return log_oom();

        r = seccomp_add_secondary_archs(seccomp);
        if (r < 0) {
                log_error_errno(r, "Failed to add secondary archs to seccomp filter: %m");
                goto finish;
        }

        r = seccomp_add_default_syscall_filter(seccomp, cap_list_retain);
        if (r < 0)
                goto finish;

        /*
           Audit is broken in containers, much of the userspace audit
           hookup will fail if running inside a container. We don't
           care and just turn off creation of audit sockets.

           This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail
           with EAFNOSUPPORT which audit userspace uses as indication
           that audit is disabled in the kernel.
         */

        r = seccomp_rule_add(
                        seccomp,
                        SCMP_ACT_ERRNO(EAFNOSUPPORT),
                        SCMP_SYS(socket),
                        2,
                        SCMP_A0(SCMP_CMP_EQ, AF_NETLINK),
                        SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT));
        if (r < 0) {
                log_error_errno(r, "Failed to add audit seccomp rule: %m");
                goto finish;
        }

        r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
        if (r < 0) {
                log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m");
                goto finish;
        }

        r = seccomp_load(seccomp);
        if (r == -EINVAL) {
                log_debug_errno(r, "Kernel is probably not configured with CONFIG_SECCOMP. Disabling seccomp audit filter: %m");
                r = 0;
                goto finish;
        }
        if (r < 0) {
                log_error_errno(r, "Failed to install seccomp audit filter: %m");
                goto finish;
        }

finish:
        seccomp_release(seccomp);
        return r;
}
Example #13
0
int waive(const int flags)
{
    scmp_filter_ctx ctx;
    int ret = -1;

    ctx = seccomp_init(SCMP_ACT_ALLOW);
    if (NULL == ctx)
        goto out;

    if (0 != (WAIVE_SOCKET & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(socket),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(socketpair),
                                  0))
            goto release;
    }
    else {
        if (0 != (WAIVE_INET & flags)) {
            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socket),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_INET)))
                goto release;

            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socket),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_INET6)))
                goto release;

            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socketpair),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_INET)))
                goto release;

            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socketpair),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_INET6)))
                goto release;
        }

        if (0 != (WAIVE_UN & flags)) {
            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socket),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_UNIX)))
                goto release;

            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socketpair),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_UNIX)))
                goto release;
        }

        if (0 != (WAIVE_PACKET & flags)) {
            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socket),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_PACKET)))
                goto release;

            if (0 != seccomp_rule_add(ctx,
                                      SCMP_ACT_ERRNO(EPERM),
                                      SCMP_SYS(socketpair),
                                      1,
                                      SCMP_A0(SCMP_CMP_EQ, AF_PACKET)))
                goto release;
        }
    }

    if (0 != (WAIVE_MOUNT & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mount),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(umount),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(umount2),
                                  0))
            goto release;
    }

    if (0 != (WAIVE_OPEN & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(open),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(openat),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(creat),
                                  0))
            goto release;
    }

    if (0 != (WAIVE_EXEC & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(execve),
                                  0))
            goto release;

#ifdef __NR_execveat
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(execveat),
                                  0))
            goto release;
#endif

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mprotect),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ, PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mprotect),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mprotect),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ, PROT_WRITE | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mprotect),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ,
                                          PROT_READ | PROT_WRITE | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mmap),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mmap),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ, PROT_WRITE | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mmap),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ,
                                          PROT_READ | PROT_WRITE | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mmap2),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ, PROT_WRITE | PROT_EXEC)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mmap2),
                                  1,
                                  SCMP_A2(SCMP_CMP_EQ,
                                          PROT_READ | PROT_WRITE | PROT_EXEC)))
            goto release;
    }

    if (0 != (WAIVE_CLONE & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(clone),
                                  0))
            goto release;
    }

    if (0 != (WAIVE_KILL & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(kill),
                                  1,
                                  SCMP_A0(SCMP_CMP_NE, 0)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(tkill),
                                  1,
                                  SCMP_A0(SCMP_CMP_NE, 0)))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(tgkill),
                                  1,
                                  SCMP_A0(SCMP_CMP_NE, 0)))
            goto release;
    }

    if (0 != (WAIVE_PIPE & flags)) {
        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(pipe),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(pipe2),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mknod),
                                  0))
            goto release;

        if (0 != seccomp_rule_add(ctx,
                                  SCMP_ACT_ERRNO(EPERM),
                                  SCMP_SYS(mknodat),
                                  0))
            goto release;
    }

    if (0 == seccomp_load(ctx))
        ret = 0;

release:
    seccomp_release(ctx);

out:
    return ret;
}
Example #14
0
gboolean
tracker_seccomp_init (void)
{
	scmp_filter_ctx ctx;

	ctx = seccomp_init (SCMP_ACT_TRAP);
	if (ctx == NULL)
		return FALSE;

	/* Memory management */
	ALLOW_RULE (brk);
	ALLOW_RULE (mmap);
	ALLOW_RULE (mmap2);
	ALLOW_RULE (munmap);
	ALLOW_RULE (mremap);
	ALLOW_RULE (mprotect);
	ALLOW_RULE (madvise);
	ERROR_RULE (mlock, EPERM);
	ERROR_RULE (mlock2, EPERM);
	ERROR_RULE (munlock, EPERM);
	ERROR_RULE (mlockall, EPERM);
	ERROR_RULE (munlockall, EPERM);
	/* Process management */
	ALLOW_RULE (exit_group);
	ALLOW_RULE (getuid);
	ALLOW_RULE (getuid32);
	ALLOW_RULE (geteuid);
	ALLOW_RULE (geteuid32);
	ALLOW_RULE (getppid);
	ALLOW_RULE (gettid);
	ALLOW_RULE (exit);
	ALLOW_RULE (getrusage);
	ALLOW_RULE (getrlimit);
	/* Basic filesystem access */
	ALLOW_RULE (fstat);
	ALLOW_RULE (fstat64);
	ALLOW_RULE (stat);
	ALLOW_RULE (stat64);
	ALLOW_RULE (statfs);
	ALLOW_RULE (statfs64);
	ALLOW_RULE (lstat);
	ALLOW_RULE (lstat64);
	ALLOW_RULE (access);
	ALLOW_RULE (getdents);
	ALLOW_RULE (getdents64);
	ALLOW_RULE (readlink);
	ALLOW_RULE (readlinkat);
	ALLOW_RULE (utime);
	ALLOW_RULE (time);
	ALLOW_RULE (fsync);
	ALLOW_RULE (umask);
	/* Processes and threads */
	ALLOW_RULE (clone);
	ALLOW_RULE (futex);
	ALLOW_RULE (set_robust_list);
	ALLOW_RULE (rt_sigaction);
	ALLOW_RULE (rt_sigprocmask);
	ALLOW_RULE (sched_yield);
	ALLOW_RULE (sched_getaffinity);
	ALLOW_RULE (nanosleep);
	/* Main loops */
	ALLOW_RULE (poll);
	ALLOW_RULE (ppoll);
	ALLOW_RULE (fcntl);
	ALLOW_RULE (fcntl64);
	ALLOW_RULE (eventfd);
	ALLOW_RULE (eventfd2);
	ALLOW_RULE (pipe);
	ALLOW_RULE (pipe2);
	/* System */
	ALLOW_RULE (uname);
	ALLOW_RULE (sysinfo);
	ALLOW_RULE (prctl);
	ALLOW_RULE (getrandom);
	ALLOW_RULE (clock_gettime);
	ALLOW_RULE (clock_getres);
	ALLOW_RULE (gettimeofday);
	/* Descriptors */
	ALLOW_RULE (close);
	ALLOW_RULE (read);
	ALLOW_RULE (pread64);
	ALLOW_RULE (lseek);
	ALLOW_RULE (_llseek);
	ALLOW_RULE (fadvise64);
	ALLOW_RULE (write);
	ALLOW_RULE (writev);
	ALLOW_RULE (dup);
	/* Needed by some GStreamer modules doing crazy stuff, less
	 * scary thanks to the restriction below about sockets being
	 * local.
	 */
	ALLOW_RULE (connect);
	ALLOW_RULE (send);
	ALLOW_RULE (sendto);
	ALLOW_RULE (sendmsg);
	ALLOW_RULE (recv);
	ALLOW_RULE (recvmsg);
	ALLOW_RULE (recvfrom);
	ALLOW_RULE (getsockname);
	ALLOW_RULE (getpeername);
	ALLOW_RULE (shutdown);

	/* Special requirements for socket/socketpair, only on AF_UNIX/AF_LOCAL */
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
	                      SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
	                      SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1,
	                      SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1,
	                      SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0)
		goto out;

	/* Special requirements for ioctl, allowed on stdout/stderr */
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1,
	                      SCMP_CMP(0, SCMP_CMP_EQ, 1)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1,
	                      SCMP_CMP(0, SCMP_CMP_EQ, 2)) < 0)
		goto out;

	/* Special requirements for open, allow O_RDONLY calls, but fail
	 * if write permissions are requested.
	 */
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1,
	                      SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1,
	                      SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1,
	                      SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) < 0)
		goto out;

	/* Special requirements for dup2/dup3, no fiddling with stdin/out/err */
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 1,
	                      SCMP_CMP(1, SCMP_CMP_GT, 2)) < 0)
		goto out;
	if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 1,
	                      SCMP_CMP(1, SCMP_CMP_GT, 2)) < 0)
		goto out;

	g_debug ("Loading seccomp rules.");

	if (seccomp_load (ctx) >= 0)
		return TRUE;

out:
	g_critical ("Failed to load seccomp rules.");
	seccomp_release (ctx);
	return FALSE;
}