| From 08edb5bc0a6d9d3d88de1e7117ce0e8044e81f60 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 17 Jun 2025 00:32:16 +0300 |
| Subject: smack: fix bug: unprivileged task can create labels |
| |
| From: Konstantin Andreev <andreev@swemel.ru> |
| |
| [ Upstream commit c147e13ea7fe9f118f8c9ba5e96cbd644b00d6b3 ] |
| |
| If an unprivileged task is allowed to relabel itself |
| (/smack/relabel-self is not empty), |
| it can freely create new labels by writing their |
| names into own /proc/PID/attr/smack/current |
| |
| This occurs because do_setattr() imports |
| the provided label in advance, |
| before checking "relabel-self" list. |
| |
| This change ensures that the "relabel-self" list |
| is checked before importing the label. |
| |
| Fixes: 38416e53936e ("Smack: limited capability for changing process label") |
| Signed-off-by: Konstantin Andreev <andreev@swemel.ru> |
| Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| security/smack/smack_lsm.c | 41 +++++++++++++++++++++++++------------- |
| 1 file changed, 27 insertions(+), 14 deletions(-) |
| |
| diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c |
| index d272cf8160d53..8d38f4a813171 100644 |
| --- a/security/smack/smack_lsm.c |
| +++ b/security/smack/smack_lsm.c |
| @@ -3687,8 +3687,8 @@ static int smack_setprocattr(const char *name, void *value, size_t size) |
| struct task_smack *tsp = smack_cred(current_cred()); |
| struct cred *new; |
| struct smack_known *skp; |
| - struct smack_known_list_elem *sklep; |
| - int rc; |
| + char *labelstr; |
| + int rc = 0; |
| |
| if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel)) |
| return -EPERM; |
| @@ -3699,28 +3699,41 @@ static int smack_setprocattr(const char *name, void *value, size_t size) |
| if (strcmp(name, "current") != 0) |
| return -EINVAL; |
| |
| - skp = smk_import_entry(value, size); |
| - if (IS_ERR(skp)) |
| - return PTR_ERR(skp); |
| + labelstr = smk_parse_smack(value, size); |
| + if (IS_ERR(labelstr)) |
| + return PTR_ERR(labelstr); |
| |
| /* |
| * No process is ever allowed the web ("@") label |
| * and the star ("*") label. |
| */ |
| - if (skp == &smack_known_web || skp == &smack_known_star) |
| - return -EINVAL; |
| + if (labelstr[1] == '\0' /* '@', '*' */) { |
| + const char c = labelstr[0]; |
| + |
| + if (c == *smack_known_web.smk_known || |
| + c == *smack_known_star.smk_known) { |
| + rc = -EPERM; |
| + goto free_labelstr; |
| + } |
| + } |
| |
| if (!smack_privileged(CAP_MAC_ADMIN)) { |
| - rc = -EPERM; |
| + const struct smack_known_list_elem *sklep; |
| list_for_each_entry(sklep, &tsp->smk_relabel, list) |
| - if (sklep->smk_label == skp) { |
| - rc = 0; |
| - break; |
| - } |
| - if (rc) |
| - return rc; |
| + if (strcmp(sklep->smk_label->smk_known, labelstr) == 0) |
| + goto free_labelstr; |
| + rc = -EPERM; |
| } |
| |
| +free_labelstr: |
| + kfree(labelstr); |
| + if (rc) |
| + return -EPERM; |
| + |
| + skp = smk_import_entry(value, size); |
| + if (IS_ERR(skp)) |
| + return PTR_ERR(skp); |
| + |
| new = prepare_creds(); |
| if (new == NULL) |
| return -ENOMEM; |
| -- |
| 2.51.0 |
| |