Skip to content

Commit 6535a84

Browse files
committed
Merge tag 'apparmor-pr-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen: "Another round of bug fixing and some code cleanups, there are no new features. The biggest thing to note is Georgia is being added to help co-maintain apparmor. Cleanups: - replace get_zeroed_page() with kzalloc() - remove unnecessary goto and associated label - change fn_label_build() to return err on failure instead of NULL or err - free rawdata as soon as possible - use explicit instead of implicit flex array in rawdata_f_data - use __label_make_stale in __aa_proxy_redirect - return correct error by propagate -ENOMEM correctly in unpack_table - aa_label_alloc use aa_label_free on alloc failure - add a conditional version of get_newest_label Bug Fixes: - mediate the implicit connect of TCP fast open sendmsg - fix C23ism of label immediately before a declaration - fix kernel-doc warnings - fix spelling mistakes - fix use-after-free in rawdata dedup loop - Fix inverted comparison in cache_hold_inc() - fix uninitialized pointer passed to audit_log_untrustedstring() - don't audit files pointing to aa_null.dentry - put secmark label after secid lookup - fix aa_getprocattr free procattr leak on format failure - release exe file resources on path failure - fail policy unpack on accept2 allocation failure - Fix return in ns_mkdir_op - remove or add symlinks to rawdata according to export_binary - fix NULL pointer dereference in unpack_pdb - fix potential UAF in aa_replace_profiles - grab ns lock and refresh when looking up changehat child profiles - enable differential encoding - check label build before no_new_privs test - conditionally compile get_loaddata_common_ref() - fix unix socket mediation cache update, and leak" * tag 'apparmor-pr-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (35 commits) apparmor: advertise the tcp fast open fix is applied apparmor: mediate the implicit connect of TCP fast open sendmsg apparmor: fix label can not be immediately before a declaration apparmor: fix kernel-doc warnings apparmor: replace get_zeroed_page() with kzalloc() security: apparmor: fix two spelling mistakes apparmor: fix use-after-free in rawdata dedup loop apparmor: Fix inverted comparison in cache_hold_inc() apparmor: fix uninitialised pointer passed to audit_log_untrustedstring() apparmor: don't audit files pointing to aa_null.dentry apparmor: put secmark label after secid lookup apparmor: aa_getprocattr free procattr leak on format failure apparmor: remove unnecessary goto and associated label apparmor: release exe file resources on path failure apparmor: fail policy unpack on accept2 allocation failure apparmor: Fix return in ns_mkdir_op apparmor: remove or add symlinks to rawdata according to export_binary apparmor: fix NULL pointer dereference in unpack_pdb apparmor: make fn_label_build() capable of handling not supported apparmor: change fn_label_build() call to not return NULL ...
2 parents e161101 + 2f6701a commit 6535a84

18 files changed

Lines changed: 368 additions & 153 deletions

File tree

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,7 @@ F: include/uapi/linux/apm_bios.h
19871987
APPARMOR SECURITY MODULE
19881988
M: John Johansen <john.johansen@canonical.com>
19891989
M: John Johansen <john@apparmor.net>
1990+
M: Georgia Garcia <georgia.garcia@canonical.com>
19901991
L: apparmor@lists.ubuntu.com (moderated for non-subscribers)
19911992
S: Supported
19921993
W: apparmor.net

security/apparmor/af_unix.c

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ static int unix_peer_perm(const struct cred *subj_cred,
615615
peer_label, &ad));
616616
}
617617

618-
/**
618+
/*
619619
*
620620
* Requires: lock held on both @sk and @peer_sk
621621
* called by unix_stream_connect, unix_may_send
@@ -674,9 +674,11 @@ static void update_sk_ctx(struct sock *sk, struct aa_label *label,
674674
old = rcu_dereference_protected(ctx->peer, lockdep_is_held(&unix_sk(sk)->lock));
675675

676676
if (old == plabel) {
677-
rcu_assign_pointer(ctx->peer_lastupdate, plabel);
677+
rcu_assign_pointer(ctx->peer_lastupdate,
678+
aa_get_label(plabel));
678679
} else if (aa_label_is_subset(plabel, old)) {
679-
rcu_assign_pointer(ctx->peer_lastupdate, plabel);
680+
rcu_assign_pointer(ctx->peer_lastupdate,
681+
aa_get_label(plabel));
680682
rcu_assign_pointer(ctx->peer, aa_get_label(plabel));
681683
aa_put_label(old);
682684
} /* else race or a subset - don't update */
@@ -748,42 +750,47 @@ int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label,
748750
if (!peer_sk)
749751
goto out;
750752

751-
peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen);
752-
753-
struct path peer_path;
754-
755-
peer_path = unix_sk(peer_sk)->path;
756-
if (!is_sk_fs && is_unix_fs(peer_sk)) {
757-
last_error(error,
758-
unix_fs_perm(op, request, subj_cred, label,
759-
is_unix_fs(peer_sk) ? &peer_path : NULL));
760-
} else if (!is_sk_fs) {
761-
struct aa_label *plabel;
762-
struct aa_sk_ctx *pctx = aa_sock(peer_sk);
763-
764-
rcu_read_lock();
765-
plabel = aa_get_label_rcu(&pctx->label);
766-
rcu_read_unlock();
767-
/* no fs check of aa_unix_peer_perm because conditions above
768-
* ensure they will never be done
769-
*/
770-
last_error(error,
771-
xcheck(unix_peer_perm(subj_cred, label, op,
753+
if (!is_sk_fs) {
754+
bool is_peer_fs = is_unix_fs(peer_sk);
755+
756+
peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen);
757+
if (is_peer_fs) {
758+
struct path peer_path;
759+
760+
unix_state_lock(peer_sk);
761+
peer_path = unix_sk(peer_sk)->path;
762+
if (peer_path.dentry)
763+
path_get(&peer_path);
764+
unix_state_unlock(peer_sk);
765+
766+
last_error(error,
767+
unix_fs_perm(op, request, subj_cred, label,
768+
&peer_path));
769+
if (peer_path.dentry)
770+
path_put(&peer_path);
771+
} else {
772+
struct aa_sk_ctx *pctx = aa_sock(peer_sk);
773+
774+
rcu_read_lock();
775+
plabel = aa_get_newest_label(pctx->label);
776+
rcu_read_unlock();
777+
/* no fs check of aa_unix_peer_perm because conditions
778+
* above ensure they will never be done
779+
*/
780+
last_error(error,
781+
xcheck(unix_peer_perm(subj_cred, label, op,
772782
MAY_READ | MAY_WRITE, sock->sk,
773783
is_sk_fs ? &path : NULL,
774784
peer_addr, peer_addrlen,
775-
is_unix_fs(peer_sk) ?
776-
&peer_path : NULL,
777-
plabel),
778-
unix_peer_perm(file->f_cred, plabel, op,
785+
NULL, plabel),
786+
unix_peer_perm(file->f_cred, plabel, op,
779787
MAY_READ | MAY_WRITE, peer_sk,
780-
is_unix_fs(peer_sk) ?
781-
&peer_path : NULL,
782-
addr, addrlen,
788+
NULL, addr, addrlen,
783789
is_sk_fs ? &path : NULL,
784790
label)));
785-
if (!error && !__aa_subj_label_is_cached(plabel, label))
786-
update_peer_ctx(peer_sk, pctx, label);
791+
if (!error && !__aa_subj_label_is_cached(plabel, label))
792+
update_peer_ctx(peer_sk, pctx, label);
793+
}
787794
}
788795
sock_put(peer_sk);
789796

security/apparmor/apparmorfs.c

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
#include <linux/ctype.h>
12+
#include <linux/slab.h>
1213
#include <linux/security.h>
1314
#include <linux/vmalloc.h>
1415
#include <linux/init.h>
@@ -71,10 +72,10 @@
7172

7273
struct rawdata_f_data {
7374
struct aa_loaddata *loaddata;
75+
DECLARE_FLEX_ARRAY(char, data);
7476
};
7577

7678
#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
77-
#define RAWDATA_F_DATA_BUF(p) (char *)(p + 1)
7879

7980
static void rawdata_f_data_free(struct rawdata_f_data *private)
8081
{
@@ -174,13 +175,15 @@ static struct aa_proxy *get_proxy_common_ref(struct aa_common_ref *ref)
174175
return NULL;
175176
}
176177

178+
#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
177179
static struct aa_loaddata *get_loaddata_common_ref(struct aa_common_ref *ref)
178180
{
179181
if (ref)
180182
return aa_get_i_loaddata(container_of(ref, struct aa_loaddata,
181183
count));
182184
return NULL;
183185
}
186+
#endif
184187

185188
static void aa_put_common_ref(struct aa_common_ref *ref)
186189
{
@@ -904,7 +907,7 @@ static void multi_transaction_kref(struct kref *kref)
904907
struct multi_transaction *t;
905908

906909
t = container_of(kref, struct multi_transaction, count);
907-
free_page((unsigned long) t);
910+
kfree(t);
908911
}
909912

910913
static struct multi_transaction *
@@ -947,7 +950,7 @@ static struct multi_transaction *multi_transaction_new(struct file *file,
947950
if (size > MULTI_TRANSACTION_LIMIT - 1)
948951
return ERR_PTR(-EFBIG);
949952

950-
t = (struct multi_transaction *)get_zeroed_page(GFP_KERNEL);
953+
t = kzalloc(PAGE_SIZE, GFP_KERNEL);
951954
if (!t)
952955
return ERR_PTR(-ENOMEM);
953956
kref_init(&t->count);
@@ -1434,7 +1437,7 @@ static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
14341437
struct rawdata_f_data *private = file->private_data;
14351438

14361439
return simple_read_from_buffer(buf, size, ppos,
1437-
RAWDATA_F_DATA_BUF(private),
1440+
private->data,
14381441
private->loaddata->size);
14391442
}
14401443

@@ -1467,8 +1470,7 @@ static int rawdata_open(struct inode *inode, struct file *file)
14671470
private->loaddata = loaddata;
14681471

14691472
error = decompress_zstd(loaddata->data, loaddata->compressed_size,
1470-
RAWDATA_F_DATA_BUF(private),
1471-
loaddata->size);
1473+
private->data, loaddata->size);
14721474
if (error)
14731475
goto fail_decompress;
14741476

@@ -1756,6 +1758,80 @@ static const struct inode_operations rawdata_link_abi_iops = {
17561758
static const struct inode_operations rawdata_link_data_iops = {
17571759
.get_link = rawdata_get_link_data,
17581760
};
1761+
1762+
/*
1763+
* Requires: @profile->ns->lock held
1764+
*/
1765+
void __aa_remove_rawdata_symlink_dents(struct aa_profile *profile)
1766+
{
1767+
aafs_remove(profile->dents[AAFS_PROF_RAW_HASH]);
1768+
profile->dents[AAFS_PROF_RAW_HASH] = NULL;
1769+
aafs_remove(profile->dents[AAFS_PROF_RAW_ABI]);
1770+
profile->dents[AAFS_PROF_RAW_ABI] = NULL;
1771+
aafs_remove(profile->dents[AAFS_PROF_RAW_DATA]);
1772+
profile->dents[AAFS_PROF_RAW_DATA] = NULL;
1773+
}
1774+
1775+
static inline int create_symlink_dent(struct aa_profile *profile,
1776+
const char *name,
1777+
enum aafs_prof_type type,
1778+
const struct inode_operations *iops)
1779+
{
1780+
struct dentry *dent = NULL;
1781+
struct dentry *dir = prof_dir(profile);
1782+
1783+
if (profile->dents[type])
1784+
return 0;
1785+
1786+
dent = aafs_create(name, S_IFLNK | 0444, dir,
1787+
&profile->label.proxy->count, NULL, NULL, iops);
1788+
if (IS_ERR(dent))
1789+
return PTR_ERR(dent);
1790+
1791+
profile->dents[type] = dent;
1792+
return 0;
1793+
}
1794+
1795+
/*
1796+
* Requires: @profile->ns->lock held
1797+
*/
1798+
int __aa_create_rawdata_symlink_dents(struct aa_profile *profile)
1799+
{
1800+
int error;
1801+
1802+
if (!profile ||
1803+
(profile->dents[AAFS_PROF_RAW_HASH] &&
1804+
profile->dents[AAFS_PROF_RAW_ABI] &&
1805+
profile->dents[AAFS_PROF_RAW_DATA]))
1806+
return 0;
1807+
1808+
if (!profile->rawdata)
1809+
return 0;
1810+
1811+
if (aa_g_hash_policy) {
1812+
error = create_symlink_dent(profile, "raw_sha256",
1813+
AAFS_PROF_RAW_HASH,
1814+
&rawdata_link_sha256_iops);
1815+
if (error)
1816+
return error;
1817+
}
1818+
1819+
error = create_symlink_dent(profile, "raw_abi",
1820+
AAFS_PROF_RAW_ABI,
1821+
&rawdata_link_abi_iops);
1822+
if (error)
1823+
return error;
1824+
1825+
1826+
error = create_symlink_dent(profile, "raw_data",
1827+
AAFS_PROF_RAW_DATA,
1828+
&rawdata_link_data_iops);
1829+
if (error)
1830+
return error;
1831+
1832+
return 0;
1833+
}
1834+
17591835
#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */
17601836

17611837
/*
@@ -1831,31 +1907,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
18311907
profile->dents[AAFS_PROF_HASH] = dent;
18321908
}
18331909

1834-
#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
1835-
if (profile->rawdata) {
1836-
if (aa_g_hash_policy) {
1837-
dent = aafs_create("raw_sha256", S_IFLNK | 0444, dir,
1838-
&profile->label.proxy->count, NULL,
1839-
NULL, &rawdata_link_sha256_iops);
1840-
if (IS_ERR(dent))
1841-
goto fail;
1842-
profile->dents[AAFS_PROF_RAW_HASH] = dent;
1843-
}
1844-
dent = aafs_create("raw_abi", S_IFLNK | 0444, dir,
1845-
&profile->label.proxy->count, NULL, NULL,
1846-
&rawdata_link_abi_iops);
1847-
if (IS_ERR(dent))
1848-
goto fail;
1849-
profile->dents[AAFS_PROF_RAW_ABI] = dent;
1850-
1851-
dent = aafs_create("raw_data", S_IFLNK | 0444, dir,
1852-
&profile->label.proxy->count, NULL, NULL,
1853-
&rawdata_link_data_iops);
1854-
if (IS_ERR(dent))
1855-
goto fail;
1856-
profile->dents[AAFS_PROF_RAW_DATA] = dent;
1857-
}
1858-
#endif /*CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */
1910+
error = __aa_create_rawdata_symlink_dents(profile);
1911+
if (error)
1912+
goto fail2;
18591913

18601914
list_for_each_entry(child, &profile->base.profiles, base.list) {
18611915
error = __aafs_profile_mkdir(child, prof_child_dir(profile));
@@ -1922,7 +1976,7 @@ static struct dentry *ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
19221976
mutex_unlock(&parent->lock);
19231977
aa_put_ns(parent);
19241978

1925-
return ERR_PTR(error);
1979+
return error ? ERR_PTR(error) : NULL;
19261980
}
19271981

19281982
static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
@@ -2422,6 +2476,7 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = {
24222476
static struct aa_sfs_entry aa_sfs_entry_policy[] = {
24232477
AA_SFS_DIR("versions", aa_sfs_entry_versions),
24242478
AA_SFS_FILE_BOOLEAN("set_load", 1),
2479+
AA_SFS_FILE_BOOLEAN("diff-encode", 1),
24252480
/* number of out of band transitions supported */
24262481
AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
24272482
AA_SFS_FILE_U64("permstable32_version", 3),

0 commit comments

Comments
 (0)