History

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

Linus Torvalds committed 2 years ago

Commit ff305642 parents 86b405a e0ff0cf8 files · +65 −34Browse files

Unified · Split

8 files
  1. security/apparmor/apparmorfs.c +4 −0
  2. security/apparmor/file.c +0 −13
  3. security/apparmor/include/cred.h +20 −0
  4. security/apparmor/lsm.c +11 −3
  5. security/apparmor/mount.c +2 −0
  6. security/apparmor/policy.c +1 −1
  7. security/apparmor/policy_unpack.c +26 −17
  8. security/apparmor/policy_unpack_test.c +1 −0
security/apparmor/apparmorfs.c+4−0
@@ -1692,6 +1692,10 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) · 1691 unmodified lines
1692 struct aa_profile *p;1692 struct aa_profile *p;
1693 p = aa_deref_parent(profile);1693 p = aa_deref_parent(profile);
1694 dent = prof_dir(p);1694 dent = prof_dir(p);
1695 if (!dent) {
1696 error = -ENOENT;
1697 goto fail2;
1698 }
1695 /* adding to parent that previously didn't have children */1699 /* adding to parent that previously didn't have children */
1696 dent = aafs_create_dir("profiles", dent);1700 dent = aafs_create_dir("profiles", dent);
1697 if (IS_ERR(dent))1701 if (IS_ERR(dent))
security/apparmor/file.c+0−13
@@ -144,19 +144,6 @@ int aa_audit_file(const struct cred *subj_cred, · 143 unmodified lines
144 return aa_audit(type, profile, &ad, file_audit_cb);144 return aa_audit(type, profile, &ad, file_audit_cb);
145}145}
146 146
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 */
153static 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
160static int path_name(const char *op, const struct cred *subj_cred,147static int path_name(const char *op, const struct cred *subj_cred,
161 struct aa_label *label,148 struct aa_label *label,
162 const struct path *path, int flags, char *buffer,149 const struct path *path, int flags, char *buffer,
security/apparmor/include/cred.h+20−0
@@ -63,6 +63,26 @@ static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred) · 62 unmodified lines
63 return aa_get_newest_label(aa_cred_raw_label(cred));63 return aa_get_newest_label(aa_cred_raw_label(cred));
64}64}
65 65
66static 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
80static inline void aa_put_label_condref(struct aa_label *l, bool needput)
81{
82 if (unlikely(needput))
83 aa_put_label(l);
84}
85
66/**86/**
67 * aa_current_raw_label - find the current tasks confining label87 * aa_current_raw_label - find the current tasks confining label
68 *88 *
security/apparmor/lsm.c+11−3
@@ -461,6 +461,7 @@ static int apparmor_file_open(struct file *file) · 460 unmodified lines
461 struct aa_file_ctx *fctx = file_ctx(file);461 struct aa_file_ctx *fctx = file_ctx(file);
462 struct aa_label *label;462 struct aa_label *label;
463 int error = 0;463 int error = 0;
464 bool needput;
464 465
465 if (!path_mediated_fs(file->f_path.dentry))466 if (!path_mediated_fs(file->f_path.dentry))
466 return 0;467 return 0;
@@ -477,7 +478,7 @@ static int apparmor_file_open(struct file *file) · 10 unmodified lines
477 return 0;478 return 0;
478 }479 }
479 480
480 label = aa_get_newest_cred_label(file->f_cred);481 label = aa_get_newest_cred_label_condref(file->f_cred, &needput);
481 if (!unconfined(label)) {482 if (!unconfined(label)) {
482 struct mnt_idmap *idmap = file_mnt_idmap(file);483 struct mnt_idmap *idmap = file_mnt_idmap(file);
483 struct inode *inode = file_inode(file);484 struct inode *inode = file_inode(file);
@@ -494,7 +495,7 @@ static int apparmor_file_open(struct file *file) · 10 unmodified lines
494 /* todo cache full allowed permissions set and state */495 /* todo cache full allowed permissions set and state */
495 fctx->allow = aa_map_file_to_perms(file);496 fctx->allow = aa_map_file_to_perms(file);
496 }497 }
497 aa_put_label(label);498 aa_put_label_condref(label, needput);
498 499
499 return error;500 return error;
500}501}
@@ -1124,7 +1125,7 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern) · 623 unmodified lines
1124 * @sock: socket that is being setup1125 * @sock: socket that is being setup
1125 * @family: family of socket being created1126 * @family: family of socket being created
1126 * @type: type of the socket1127 * @type: type of the socket
1127 * @ptotocol: protocol of the socket1128 * @protocol: protocol of the socket
1128 * @kern: socket is a special kernel socket1129 * @kern: socket is a special kernel socket
1129 *1130 *
1130 * Note:1131 * Note:
@@ -1304,6 +1305,13 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) · 173 unmodified lines
1304 if (!skb->secmark)1305 if (!skb->secmark)
1305 return 0;1306 return 0;
1306 1307
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
1307 return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE,1315 return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE,
1308 skb->secmark, sk);1316 skb->secmark, sk);
1309}1317}
security/apparmor/mount.c+2−0
@@ -44,6 +44,8 @@ static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) · 43 unmodified lines
44 audit_log_format(ab, ", mand");44 audit_log_format(ab, ", mand");
45 if (flags & MS_DIRSYNC)45 if (flags & MS_DIRSYNC)
46 audit_log_format(ab, ", dirsync");46 audit_log_format(ab, ", dirsync");
47 if (flags & MS_NOSYMFOLLOW)
48 audit_log_format(ab, ", nosymfollow");
47 if (flags & MS_NOATIME)49 if (flags & MS_NOATIME)
48 audit_log_format(ab, ", noatime");50 audit_log_format(ab, ", noatime");
49 if (flags & MS_NODIRATIME)51 if (flags & MS_NODIRATIME)
security/apparmor/policy.c+1−1
@@ -225,7 +225,7 @@ static void aa_free_data(void *ptr, void *arg) · 224 unmodified lines
225{225{
226 struct aa_data *data = ptr;226 struct aa_data *data = ptr;
227 227
228 kfree_sensitive(data->data);228 kvfree_sensitive(data->data, data->size);
229 kfree_sensitive(data->key);229 kfree_sensitive(data->key);
230 kfree_sensitive(data);230 kfree_sensitive(data);
231}231}
security/apparmor/policy_unpack.c+26−17
@@ -747,34 +747,42 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy, · 746 unmodified lines
747 *info = "missing required dfa";747 *info = "missing required dfa";
748 goto fail;748 goto fail;
749 }749 }
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 }
751 }768 }
752 769
753 /*770 /*
754 * only unpack the following if a dfa is present771 * Unfortunately due to a bug in earlier userspaces, a
755 *772 * transition table may be present even when the dfa is
756 * sadly start was given different names for file and policydb773 * not. For compatibility reasons unpack and discard.
757 * but since it is optional we can try both
758 */774 */
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 }
770 if (!unpack_trans_table(e, &pdb->trans) && required_trans) {775 if (!unpack_trans_table(e, &pdb->trans) && required_trans) {
771 *info = "failed to unpack profile transition table";776 *info = "failed to unpack profile transition table";
772 goto fail;777 goto fail;
773 }778 }
774 779
780 if (!pdb->dfa && pdb->trans.table)
781 aa_free_str_table(&pdb->trans);
782
775 /* TODO: move compat mapping here, requires dfa merging first */783 /* TODO: move compat mapping here, requires dfa merging first */
776 /* TODO: move verify here, it has to be done after compat mappings */784 /* TODO: move verify here, it has to be done after compat mappings */
777out:785
778 *policy = pdb;786 *policy = pdb;
779 return 0;787 return 0;
780 788
@@ -1071,6 +1079,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) · 290 unmodified lines
1071 1079
1072 if (rhashtable_insert_fast(profile->data, &data->head,1080 if (rhashtable_insert_fast(profile->data, &data->head,
1073 profile->data->p)) {1081 profile->data->p)) {
1082 kvfree_sensitive(data->data, data->size);
1074 kfree_sensitive(data->key);1083 kfree_sensitive(data->key);
1075 kfree_sensitive(data);1084 kfree_sensitive(data);
1076 info = "failed to insert data to table";1085 info = "failed to insert data to table";
security/apparmor/policy_unpack_test.c+1−0
@@ -604,4 +604,5 @@ static struct kunit_suite apparmor_policy_unpack_test_module = { · 603 unmodified lines
604 604
605kunit_test_suite(apparmor_policy_unpack_test_module);605kunit_test_suite(apparmor_policy_unpack_test_module);
606 606
607MODULE_DESCRIPTION("KUnit tests for AppArmor's policy unpack");
607MODULE_LICENSE("GPL");608MODULE_LICENSE("GPL");