Skip to content

Commit ff30564

Browse files
committed
Merge tag 'apparmor-pr-2024-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen: "Cleanups - optimization: try to avoid refing the label in apparmor_file_open - remove useless static inline function is_deleted - use kvfree_sensitive to free data->data - fix typo in kernel doc Bug fixes: - unpack transition table if dfa is not present - test: add MODULE_DESCRIPTION() - take nosymfollow flag into account - fix possible NULL pointer dereference - fix null pointer deref when receiving skb during sock creation" * tag 'apparmor-pr-2024-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: apparmor: unpack transition table if dfa is not present apparmor: try to avoid refing the label in apparmor_file_open apparmor: test: add MODULE_DESCRIPTION() apparmor: take nosymfollow flag into account apparmor: fix possible NULL pointer dereference apparmor: fix typo in kernel doc apparmor: remove useless static inline function is_deleted apparmor: use kvfree_sensitive to free data->data apparmor: Fix null pointer deref when receiving skb during sock creation
2 parents 86b405a + e0ff0cf commit ff30564

File tree

8 files changed

+65
-34
lines changed

8 files changed

+65
-34
lines changed

security/apparmor/apparmorfs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,6 +1692,10 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
16921692
struct aa_profile *p;
16931693
p = aa_deref_parent(profile);
16941694
dent = prof_dir(p);
1695+
if (!dent) {
1696+
error = -ENOENT;
1697+
goto fail2;
1698+
}
16951699
/* adding to parent that previously didn't have children */
16961700
dent = aafs_create_dir("profiles", dent);
16971701
if (IS_ERR(dent))

security/apparmor/file.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,6 @@ int aa_audit_file(const struct cred *subj_cred,
144144
return aa_audit(type, profile, &ad, file_audit_cb);
145145
}
146146

147-
/**
148-
* is_deleted - test if a file has been completely unlinked
149-
* @dentry: dentry of file to test for deletion (NOT NULL)
150-
*
151-
* Returns: true if deleted else false
152-
*/
153-
static inline bool is_deleted(struct dentry *dentry)
154-
{
155-
if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
156-
return true;
157-
return false;
158-
}
159-
160147
static int path_name(const char *op, const struct cred *subj_cred,
161148
struct aa_label *label,
162149
const struct path *path, int flags, char *buffer,

security/apparmor/include/cred.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred)
6363
return aa_get_newest_label(aa_cred_raw_label(cred));
6464
}
6565

66+
static inline struct aa_label *aa_get_newest_cred_label_condref(const struct cred *cred,
67+
bool *needput)
68+
{
69+
struct aa_label *l = aa_cred_raw_label(cred);
70+
71+
if (unlikely(label_is_stale(l))) {
72+
*needput = true;
73+
return aa_get_newest_label(l);
74+
}
75+
76+
*needput = false;
77+
return l;
78+
}
79+
80+
static inline void aa_put_label_condref(struct aa_label *l, bool needput)
81+
{
82+
if (unlikely(needput))
83+
aa_put_label(l);
84+
}
85+
6686
/**
6787
* aa_current_raw_label - find the current tasks confining label
6888
*

security/apparmor/lsm.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ static int apparmor_file_open(struct file *file)
461461
struct aa_file_ctx *fctx = file_ctx(file);
462462
struct aa_label *label;
463463
int error = 0;
464+
bool needput;
464465

465466
if (!path_mediated_fs(file->f_path.dentry))
466467
return 0;
@@ -477,7 +478,7 @@ static int apparmor_file_open(struct file *file)
477478
return 0;
478479
}
479480

480-
label = aa_get_newest_cred_label(file->f_cred);
481+
label = aa_get_newest_cred_label_condref(file->f_cred, &needput);
481482
if (!unconfined(label)) {
482483
struct mnt_idmap *idmap = file_mnt_idmap(file);
483484
struct inode *inode = file_inode(file);
@@ -494,7 +495,7 @@ static int apparmor_file_open(struct file *file)
494495
/* todo cache full allowed permissions set and state */
495496
fctx->allow = aa_map_file_to_perms(file);
496497
}
497-
aa_put_label(label);
498+
aa_put_label_condref(label, needput);
498499

499500
return error;
500501
}
@@ -1124,7 +1125,7 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern)
11241125
* @sock: socket that is being setup
11251126
* @family: family of socket being created
11261127
* @type: type of the socket
1127-
* @ptotocol: protocol of the socket
1128+
* @protocol: protocol of the socket
11281129
* @kern: socket is a special kernel socket
11291130
*
11301131
* Note:
@@ -1304,6 +1305,13 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
13041305
if (!skb->secmark)
13051306
return 0;
13061307

1308+
/*
1309+
* If reach here before socket_post_create hook is called, in which
1310+
* case label is null, drop the packet.
1311+
*/
1312+
if (!ctx->label)
1313+
return -EACCES;
1314+
13071315
return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE,
13081316
skb->secmark, sk);
13091317
}

security/apparmor/mount.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
4444
audit_log_format(ab, ", mand");
4545
if (flags & MS_DIRSYNC)
4646
audit_log_format(ab, ", dirsync");
47+
if (flags & MS_NOSYMFOLLOW)
48+
audit_log_format(ab, ", nosymfollow");
4749
if (flags & MS_NOATIME)
4850
audit_log_format(ab, ", noatime");
4951
if (flags & MS_NODIRATIME)

security/apparmor/policy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ static void aa_free_data(void *ptr, void *arg)
225225
{
226226
struct aa_data *data = ptr;
227227

228-
kfree_sensitive(data->data);
228+
kvfree_sensitive(data->data, data->size);
229229
kfree_sensitive(data->key);
230230
kfree_sensitive(data);
231231
}

security/apparmor/policy_unpack.c

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -747,34 +747,42 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
747747
*info = "missing required dfa";
748748
goto fail;
749749
}
750-
goto out;
750+
} else {
751+
/*
752+
* only unpack the following if a dfa is present
753+
*
754+
* sadly start was given different names for file and policydb
755+
* but since it is optional we can try both
756+
*/
757+
if (!aa_unpack_u32(e, &pdb->start[0], "start"))
758+
/* default start state */
759+
pdb->start[0] = DFA_START;
760+
if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) {
761+
/* default start state for xmatch and file dfa */
762+
pdb->start[AA_CLASS_FILE] = DFA_START;
763+
} /* setup class index */
764+
for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) {
765+
pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0],
766+
i);
767+
}
751768
}
752769

753770
/*
754-
* only unpack the following if a dfa is present
755-
*
756-
* sadly start was given different names for file and policydb
757-
* but since it is optional we can try both
771+
* Unfortunately due to a bug in earlier userspaces, a
772+
* transition table may be present even when the dfa is
773+
* not. For compatibility reasons unpack and discard.
758774
*/
759-
if (!aa_unpack_u32(e, &pdb->start[0], "start"))
760-
/* default start state */
761-
pdb->start[0] = DFA_START;
762-
if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) {
763-
/* default start state for xmatch and file dfa */
764-
pdb->start[AA_CLASS_FILE] = DFA_START;
765-
} /* setup class index */
766-
for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) {
767-
pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0],
768-
i);
769-
}
770775
if (!unpack_trans_table(e, &pdb->trans) && required_trans) {
771776
*info = "failed to unpack profile transition table";
772777
goto fail;
773778
}
774779

780+
if (!pdb->dfa && pdb->trans.table)
781+
aa_free_str_table(&pdb->trans);
782+
775783
/* TODO: move compat mapping here, requires dfa merging first */
776784
/* TODO: move verify here, it has to be done after compat mappings */
777-
out:
785+
778786
*policy = pdb;
779787
return 0;
780788

@@ -1071,6 +1079,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
10711079

10721080
if (rhashtable_insert_fast(profile->data, &data->head,
10731081
profile->data->p)) {
1082+
kvfree_sensitive(data->data, data->size);
10741083
kfree_sensitive(data->key);
10751084
kfree_sensitive(data);
10761085
info = "failed to insert data to table";

security/apparmor/policy_unpack_test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,4 +604,5 @@ static struct kunit_suite apparmor_policy_unpack_test_module = {
604604

605605
kunit_test_suite(apparmor_policy_unpack_test_module);
606606

607+
MODULE_DESCRIPTION("KUnit tests for AppArmor's policy unpack");
607608
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)