core: firewall integration with DynamicUserNFTSet=

New directive `DynamicUserNFTSet=` provides a method for integrating
configuration of dynamic users into firewall rules with NFT sets.

Example:
```
table inet filter {
        set u {
                typeof meta skuid
        }

        chain service_output {
                meta skuid != @u drop
                accept
        }
}
```

```
/etc/systemd/system/dunft.service
[Service]
DynamicUser=yes
DynamicUserNFTSet=inet:filter:u
ExecStart=/bin/sleep 1000

[Install]
WantedBy=multi-user.target
```

```
$ sudo nft list set inet filter u
table inet filter {
        set u {
                typeof meta skuid
                elements = { 64864 }
        }
}
$ ps -n --format user,group,pid,command -p `pgrep sleep`
    USER    GROUP     PID COMMAND
   64864    64864   55158 /bin/sleep 1000
```
This commit is contained in:
Topi Miettinen
2022-06-08 16:12:25 +00:00
committed by Topi Miettinen
parent c0548df0a2
commit 46c3b1ff88
14 changed files with 310 additions and 0 deletions
+46
View File
@@ -4083,6 +4083,43 @@ static int add_shifted_fd(int *fds, size_t fds_size, size_t *n_fds, int fd, int
return 1;
}
static void exec_op_dynamic_user_nft_set(bool add, const ExecContext *c, uid_t uid) {
int r;
assert(c);
for (size_t i = 0; i < c->n_dynamic_user_nft_set_contexts; i++) {
NFTSetContext *s = &c->dynamic_user_nft_set_context[i];
if (add)
r = nft_set_element_add_uint32(s, uid);
else
r = nft_set_element_del_uint32(s, uid);
if (r < 0)
log_warning_errno(r, "%s NFT family %s table %s set %s UID " UID_FMT " failed, ignoring: %m",
add? "Adding" : "Deleting", nfproto_to_string(s->nfproto), s->table, s->set, uid);
}
}
static void exec_add_dynamic_user_nft_set(const ExecContext *c, uid_t uid) {
exec_op_dynamic_user_nft_set(true, c, uid);
}
void exec_delete_dynamic_user_nft_set(const ExecContext *c, DynamicUser *d) {
int r;
uid_t uid;
if (!d)
return;
r = dynamic_user_current(d, &uid);
if (r < 0) {
log_warning_errno(r, "Can't get current dynamic user, ignoring: %m");
return;
}
exec_op_dynamic_user_nft_set(false, c, uid);
}
static int exec_child(
Unit *unit,
const ExecCommand *command,
@@ -4284,6 +4321,8 @@ static int exec_child(
if (dcreds->user)
username = dcreds->user->name;
exec_add_dynamic_user_nft_set(context, uid);
} else {
r = get_fixed_user(context, &username, &uid, &gid, &home, &shell);
if (r < 0) {
@@ -5346,6 +5385,8 @@ void exec_context_done(ExecContext *c) {
c->user = mfree(c->user);
c->group = mfree(c->group);
c->dynamic_user_nft_set_context = nft_set_context_free_many(c->dynamic_user_nft_set_context, &c->n_dynamic_user_nft_set_contexts);
c->supplementary_groups = strv_free(c->supplementary_groups);
c->pam_name = mfree(c->pam_name);
@@ -6020,6 +6061,11 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
fprintf(f, "%sGroup: %s\n", prefix, c->group);
fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
for (size_t i = 0; i < c->n_dynamic_user_nft_set_contexts; i++)
fprintf(f, "%sDynamicUserNFTSet: %s:%s:%s\n", prefix,
nfproto_to_string(c->dynamic_user_nft_set_context[i].nfproto),
c->dynamic_user_nft_set_context[i].table,
c->dynamic_user_nft_set_context[i].set);
strv_dump(f, prefix, "SupplementaryGroups", c->supplementary_groups);