+ /* No entries in the valid range, block everything */
+ r = seccomp_rule_add(
+ seccomp,
+ SCMP_ACT_ERRNO(EPROTONOSUPPORT),
+ SCMP_SYS(socket),
+ 0);
+ if (r < 0)
+ goto finish;
+
+ } else {
+
+ /* Block everything below the first entry */
+ r = seccomp_rule_add(
+ seccomp,
+ SCMP_ACT_ERRNO(EPROTONOSUPPORT),
+ SCMP_SYS(socket),
+ 1,
+ SCMP_A0(SCMP_CMP_LT, first));
+ if (r < 0)
+ goto finish;
+
+ /* Block everything above the last entry */
+ r = seccomp_rule_add(
+ seccomp,
+ SCMP_ACT_ERRNO(EPROTONOSUPPORT),
+ SCMP_SYS(socket),
+ 1,
+ SCMP_A0(SCMP_CMP_GT, last));
+ if (r < 0)
+ goto finish;
+
+ /* Block everything between the first and last
+ * entry */
+ for (af = 1; af < af_max(); af++) {
+
+ if (set_contains(c->address_families, INT_TO_PTR(af)))
+ continue;
+
+ r = seccomp_rule_add(
+ seccomp,
+ SCMP_ACT_ERRNO(EPROTONOSUPPORT),
+ SCMP_SYS(socket),
+ 1,
+ SCMP_A0(SCMP_CMP_EQ, af));
+ if (r < 0)
+ goto finish;
+ }
+ }
+
+ } else {
+ void *af;
+
+ /* If this is a blacklist, then generate one rule for
+ * each address family that are then combined in OR
+ * checks. */
+
+ SET_FOREACH(af, c->address_families, i) {
+
+ r = seccomp_rule_add(
+ seccomp,
+ SCMP_ACT_ERRNO(EPROTONOSUPPORT),
+ SCMP_SYS(socket),
+ 1,
+ SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af)));
+ if (r < 0)
+ goto finish;
+ }
+ }
+
+ r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
+ if (r < 0)
+ goto finish;
+
+ r = seccomp_load(seccomp);
+
+finish:
+ seccomp_release(seccomp);