Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

apparmor: fix race between freeing data and fs accessing it

AppArmor was putting the reference to i_private data on its end after
removing the original entry from the file system. However the inode
can aand does live beyond that point and it is possible that some of
the fs call back functions will be invoked after the reference has
been put, which results in a race between freeing the data and
accessing it through the fs.

While the rawdata/loaddata is the most likely candidate to fail the
race, as it has the fewest references. If properly crafted it might be
possible to trigger a race for the other types stored in i_private.

Fix this by moving the put of i_private referenced data to the correct
place which is during inode eviction.

Fixes: c961ee5f21b20 ("apparmor: convert from securityfs to apparmorfs for policy ns files")
Reported-by: Qualys Security Advisory <qsa@qualys.com>
Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Reviewed-by: Maxime Bélair <maxime.belair@canonical.com>
Reviewed-by: Cengiz Can <cengiz.can@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>

+153 -101
+114 -80
security/apparmor/apparmorfs.c
··· 32 32 #include "include/crypto.h" 33 33 #include "include/ipc.h" 34 34 #include "include/label.h" 35 + #include "include/lib.h" 35 36 #include "include/policy.h" 36 37 #include "include/policy_ns.h" 37 38 #include "include/resource.h" ··· 63 62 * securityfs and apparmorfs filesystems. 64 63 */ 65 64 65 + #define IREF_POISON 101 66 66 67 67 /* 68 68 * support fns ··· 155 153 return 0; 156 154 } 157 155 156 + static struct aa_ns *get_ns_common_ref(struct aa_common_ref *ref) 157 + { 158 + if (ref) { 159 + struct aa_label *reflabel = container_of(ref, struct aa_label, 160 + count); 161 + return aa_get_ns(labels_ns(reflabel)); 162 + } 163 + 164 + return NULL; 165 + } 166 + 167 + static struct aa_proxy *get_proxy_common_ref(struct aa_common_ref *ref) 168 + { 169 + if (ref) 170 + return aa_get_proxy(container_of(ref, struct aa_proxy, count)); 171 + 172 + return NULL; 173 + } 174 + 175 + static struct aa_loaddata *get_loaddata_common_ref(struct aa_common_ref *ref) 176 + { 177 + if (ref) 178 + return aa_get_i_loaddata(container_of(ref, struct aa_loaddata, 179 + count)); 180 + return NULL; 181 + } 182 + 183 + static void aa_put_common_ref(struct aa_common_ref *ref) 184 + { 185 + if (!ref) 186 + return; 187 + 188 + switch (ref->reftype) { 189 + case REF_RAWDATA: 190 + aa_put_i_loaddata(container_of(ref, struct aa_loaddata, 191 + count)); 192 + break; 193 + case REF_PROXY: 194 + aa_put_proxy(container_of(ref, struct aa_proxy, 195 + count)); 196 + break; 197 + case REF_NS: 198 + /* ns count is held on its unconfined label */ 199 + aa_put_ns(labels_ns(container_of(ref, struct aa_label, count))); 200 + break; 201 + default: 202 + AA_BUG(true, "unknown refcount type"); 203 + break; 204 + } 205 + } 206 + 207 + static void aa_get_common_ref(struct aa_common_ref *ref) 208 + { 209 + kref_get(&ref->count); 210 + } 211 + 212 + static void aafs_evict(struct inode *inode) 213 + { 214 + struct aa_common_ref *ref = inode->i_private; 215 + 216 + clear_inode(inode); 217 + aa_put_common_ref(ref); 218 + inode->i_private = (void *) IREF_POISON; 219 + } 220 + 158 221 static void aafs_free_inode(struct inode *inode) 159 222 { 160 223 if (S_ISLNK(inode->i_mode)) ··· 229 162 230 163 static const struct super_operations aafs_super_ops = { 231 164 .statfs = simple_statfs, 165 + .evict_inode = aafs_evict, 232 166 .free_inode = aafs_free_inode, 233 167 .show_path = aafs_show_path, 234 168 }; ··· 330 262 * aafs_remove(). Will return ERR_PTR on failure. 331 263 */ 332 264 static struct dentry *aafs_create(const char *name, umode_t mode, 333 - struct dentry *parent, void *data, void *link, 265 + struct dentry *parent, 266 + struct aa_common_ref *data, void *link, 334 267 const struct file_operations *fops, 335 268 const struct inode_operations *iops) 336 269 { ··· 368 299 goto fail_dentry; 369 300 inode_unlock(dir); 370 301 302 + if (data) 303 + aa_get_common_ref(data); 304 + 371 305 return dentry; 372 306 373 307 fail_dentry: ··· 395 323 * see aafs_create 396 324 */ 397 325 static struct dentry *aafs_create_file(const char *name, umode_t mode, 398 - struct dentry *parent, void *data, 326 + struct dentry *parent, 327 + struct aa_common_ref *data, 399 328 const struct file_operations *fops) 400 329 { 401 330 return aafs_create(name, mode, parent, data, NULL, fops, NULL); ··· 526 453 static ssize_t profile_load(struct file *f, const char __user *buf, size_t size, 527 454 loff_t *pos) 528 455 { 529 - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); 456 + struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private); 530 457 int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns, 531 458 f->f_cred); 532 459 ··· 544 471 static ssize_t profile_replace(struct file *f, const char __user *buf, 545 472 size_t size, loff_t *pos) 546 473 { 547 - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); 474 + struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private); 548 475 int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY, 549 476 buf, size, pos, ns, f->f_cred); 550 477 aa_put_ns(ns); ··· 564 491 struct aa_loaddata *data; 565 492 struct aa_label *label; 566 493 ssize_t error; 567 - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); 494 + struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private); 568 495 569 496 label = begin_current_label_crit_section(); 570 497 /* high level check about policy management - fine grained in ··· 654 581 if (!rev) 655 582 return -ENOMEM; 656 583 657 - rev->ns = aa_get_ns(inode->i_private); 584 + rev->ns = get_ns_common_ref(inode->i_private); 658 585 if (!rev->ns) 659 586 rev->ns = aa_get_current_ns(); 660 587 file->private_data = rev; ··· 1140 1067 static int seq_profile_open(struct inode *inode, struct file *file, 1141 1068 int (*show)(struct seq_file *, void *)) 1142 1069 { 1143 - struct aa_proxy *proxy = aa_get_proxy(inode->i_private); 1070 + struct aa_proxy *proxy = get_proxy_common_ref(inode->i_private); 1144 1071 int error = single_open(file, show, proxy); 1145 1072 1146 1073 if (error) { ··· 1332 1259 static int seq_rawdata_open(struct inode *inode, struct file *file, 1333 1260 int (*show)(struct seq_file *, void *)) 1334 1261 { 1335 - struct aa_loaddata *data = aa_get_i_loaddata(inode->i_private); 1262 + struct aa_loaddata *data = get_loaddata_common_ref(inode->i_private); 1336 1263 int error; 1337 1264 1338 1265 if (!data) ··· 1465 1392 if (!aa_current_policy_view_capable(NULL)) 1466 1393 return -EACCES; 1467 1394 1468 - loaddata = aa_get_i_loaddata(inode->i_private); 1395 + loaddata = get_loaddata_common_ref(inode->i_private); 1469 1396 if (!loaddata) 1470 1397 return -ENOENT; 1471 1398 ··· 1510 1437 if (!IS_ERR_OR_NULL(rawdata->dents[i])) { 1511 1438 aafs_remove(rawdata->dents[i]); 1512 1439 rawdata->dents[i] = NULL; 1513 - aa_put_i_loaddata(rawdata); 1514 1440 } 1515 1441 } 1516 1442 } ··· 1548 1476 if (IS_ERR(dir)) 1549 1477 /* ->name freed when rawdata freed */ 1550 1478 return PTR_ERR(dir); 1551 - aa_get_i_loaddata(rawdata); 1552 1479 rawdata->dents[AAFS_LOADDATA_DIR] = dir; 1553 1480 1554 - dent = aafs_create_file("abi", S_IFREG | 0444, dir, rawdata, 1481 + dent = aafs_create_file("abi", S_IFREG | 0444, dir, &rawdata->count, 1555 1482 &seq_rawdata_abi_fops); 1556 1483 if (IS_ERR(dent)) 1557 1484 goto fail; 1558 - aa_get_i_loaddata(rawdata); 1559 1485 rawdata->dents[AAFS_LOADDATA_ABI] = dent; 1560 1486 1561 - dent = aafs_create_file("revision", S_IFREG | 0444, dir, rawdata, 1562 - &seq_rawdata_revision_fops); 1487 + dent = aafs_create_file("revision", S_IFREG | 0444, dir, 1488 + &rawdata->count, 1489 + &seq_rawdata_revision_fops); 1563 1490 if (IS_ERR(dent)) 1564 1491 goto fail; 1565 - aa_get_i_loaddata(rawdata); 1566 1492 rawdata->dents[AAFS_LOADDATA_REVISION] = dent; 1567 1493 1568 1494 if (aa_g_hash_policy) { 1569 1495 dent = aafs_create_file("sha256", S_IFREG | 0444, dir, 1570 - rawdata, &seq_rawdata_hash_fops); 1496 + &rawdata->count, 1497 + &seq_rawdata_hash_fops); 1571 1498 if (IS_ERR(dent)) 1572 1499 goto fail; 1573 - aa_get_i_loaddata(rawdata); 1574 1500 rawdata->dents[AAFS_LOADDATA_HASH] = dent; 1575 1501 } 1576 1502 1577 1503 dent = aafs_create_file("compressed_size", S_IFREG | 0444, dir, 1578 - rawdata, 1504 + &rawdata->count, 1579 1505 &seq_rawdata_compressed_size_fops); 1580 1506 if (IS_ERR(dent)) 1581 1507 goto fail; 1582 - aa_get_i_loaddata(rawdata); 1583 1508 rawdata->dents[AAFS_LOADDATA_COMPRESSED_SIZE] = dent; 1584 1509 1585 - dent = aafs_create_file("raw_data", S_IFREG | 0444, 1586 - dir, rawdata, &rawdata_fops); 1510 + dent = aafs_create_file("raw_data", S_IFREG | 0444, dir, 1511 + &rawdata->count, &rawdata_fops); 1587 1512 if (IS_ERR(dent)) 1588 1513 goto fail; 1589 - aa_get_i_loaddata(rawdata); 1590 1514 rawdata->dents[AAFS_LOADDATA_DATA] = dent; 1591 1515 d_inode(dent)->i_size = rawdata->size; 1592 1516 ··· 1593 1525 1594 1526 fail: 1595 1527 remove_rawdata_dents(rawdata); 1596 - aa_put_i_loaddata(rawdata); 1597 1528 return PTR_ERR(dent); 1598 1529 } 1599 1530 #endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ ··· 1616 1549 __aafs_profile_rmdir(child); 1617 1550 1618 1551 for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) { 1619 - struct aa_proxy *proxy; 1620 1552 if (!profile->dents[i]) 1621 1553 continue; 1622 1554 1623 - proxy = d_inode(profile->dents[i])->i_private; 1624 1555 aafs_remove(profile->dents[i]); 1625 - aa_put_proxy(proxy); 1626 1556 profile->dents[i] = NULL; 1627 1557 } 1628 1558 } ··· 1653 1589 struct aa_profile *profile, 1654 1590 const struct file_operations *fops) 1655 1591 { 1656 - struct aa_proxy *proxy = aa_get_proxy(profile->label.proxy); 1657 - struct dentry *dent; 1658 - 1659 - dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops); 1660 - if (IS_ERR(dent)) 1661 - aa_put_proxy(proxy); 1662 - 1663 - return dent; 1592 + return aafs_create_file(name, S_IFREG | 0444, dir, &profile->label.proxy->count, fops); 1664 1593 } 1665 1594 1666 1595 #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY ··· 1703 1646 struct delayed_call *done, 1704 1647 const char *name) 1705 1648 { 1706 - struct aa_proxy *proxy = inode->i_private; 1649 + struct aa_common_ref *ref = inode->i_private; 1650 + struct aa_proxy *proxy = container_of(ref, struct aa_proxy, count); 1707 1651 struct aa_label *label; 1708 1652 struct aa_profile *profile; 1709 1653 char *target; ··· 1846 1788 if (profile->rawdata) { 1847 1789 if (aa_g_hash_policy) { 1848 1790 dent = aafs_create("raw_sha256", S_IFLNK | 0444, dir, 1849 - profile->label.proxy, NULL, NULL, 1850 - &rawdata_link_sha256_iops); 1791 + &profile->label.proxy->count, NULL, 1792 + NULL, &rawdata_link_sha256_iops); 1851 1793 if (IS_ERR(dent)) 1852 1794 goto fail; 1853 - aa_get_proxy(profile->label.proxy); 1854 1795 profile->dents[AAFS_PROF_RAW_HASH] = dent; 1855 1796 } 1856 1797 dent = aafs_create("raw_abi", S_IFLNK | 0444, dir, 1857 - profile->label.proxy, NULL, NULL, 1798 + &profile->label.proxy->count, NULL, NULL, 1858 1799 &rawdata_link_abi_iops); 1859 1800 if (IS_ERR(dent)) 1860 1801 goto fail; 1861 - aa_get_proxy(profile->label.proxy); 1862 1802 profile->dents[AAFS_PROF_RAW_ABI] = dent; 1863 1803 1864 1804 dent = aafs_create("raw_data", S_IFLNK | 0444, dir, 1865 - profile->label.proxy, NULL, NULL, 1805 + &profile->label.proxy->count, NULL, NULL, 1866 1806 &rawdata_link_data_iops); 1867 1807 if (IS_ERR(dent)) 1868 1808 goto fail; 1869 - aa_get_proxy(profile->label.proxy); 1870 1809 profile->dents[AAFS_PROF_RAW_DATA] = dent; 1871 1810 } 1872 1811 #endif /*CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ ··· 1900 1845 if (error) 1901 1846 return ERR_PTR(error); 1902 1847 1903 - parent = aa_get_ns(dir->i_private); 1848 + parent = get_ns_common_ref(dir->i_private); 1904 1849 AA_BUG(d_inode(ns_subns_dir(parent)) != dir); 1905 1850 1906 1851 /* we have to unlock and then relock to get locking order right ··· 1950 1895 if (error) 1951 1896 return error; 1952 1897 1953 - parent = aa_get_ns(dir->i_private); 1898 + parent = get_ns_common_ref(dir->i_private); 1954 1899 /* rmdir calls the generic securityfs functions to remove files 1955 1900 * from the apparmor dir. It is up to the apparmor ns locking 1956 1901 * to avoid races. ··· 2020 1965 2021 1966 __aa_fs_list_remove_rawdata(ns); 2022 1967 2023 - if (ns_subns_dir(ns)) { 2024 - sub = d_inode(ns_subns_dir(ns))->i_private; 2025 - aa_put_ns(sub); 2026 - } 2027 - if (ns_subload(ns)) { 2028 - sub = d_inode(ns_subload(ns))->i_private; 2029 - aa_put_ns(sub); 2030 - } 2031 - if (ns_subreplace(ns)) { 2032 - sub = d_inode(ns_subreplace(ns))->i_private; 2033 - aa_put_ns(sub); 2034 - } 2035 - if (ns_subremove(ns)) { 2036 - sub = d_inode(ns_subremove(ns))->i_private; 2037 - aa_put_ns(sub); 2038 - } 2039 - if (ns_subrevision(ns)) { 2040 - sub = d_inode(ns_subrevision(ns))->i_private; 2041 - aa_put_ns(sub); 2042 - } 2043 - 2044 1968 for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) { 2045 1969 aafs_remove(ns->dents[i]); 2046 1970 ns->dents[i] = NULL; ··· 2044 2010 return PTR_ERR(dent); 2045 2011 ns_subdata_dir(ns) = dent; 2046 2012 2047 - dent = aafs_create_file("revision", 0444, dir, ns, 2013 + dent = aafs_create_file("revision", 0444, dir, 2014 + &ns->unconfined->label.count, 2048 2015 &aa_fs_ns_revision_fops); 2049 2016 if (IS_ERR(dent)) 2050 2017 return PTR_ERR(dent); 2051 - aa_get_ns(ns); 2052 2018 ns_subrevision(ns) = dent; 2053 2019 2054 - dent = aafs_create_file(".load", 0640, dir, ns, 2055 - &aa_fs_profile_load); 2020 + dent = aafs_create_file(".load", 0640, dir, 2021 + &ns->unconfined->label.count, 2022 + &aa_fs_profile_load); 2056 2023 if (IS_ERR(dent)) 2057 2024 return PTR_ERR(dent); 2058 - aa_get_ns(ns); 2059 2025 ns_subload(ns) = dent; 2060 2026 2061 - dent = aafs_create_file(".replace", 0640, dir, ns, 2062 - &aa_fs_profile_replace); 2027 + dent = aafs_create_file(".replace", 0640, dir, 2028 + &ns->unconfined->label.count, 2029 + &aa_fs_profile_replace); 2063 2030 if (IS_ERR(dent)) 2064 2031 return PTR_ERR(dent); 2065 - aa_get_ns(ns); 2066 2032 ns_subreplace(ns) = dent; 2067 2033 2068 - dent = aafs_create_file(".remove", 0640, dir, ns, 2069 - &aa_fs_profile_remove); 2034 + dent = aafs_create_file(".remove", 0640, dir, 2035 + &ns->unconfined->label.count, 2036 + &aa_fs_profile_remove); 2070 2037 if (IS_ERR(dent)) 2071 2038 return PTR_ERR(dent); 2072 - aa_get_ns(ns); 2073 2039 ns_subremove(ns) = dent; 2074 2040 2075 2041 /* use create_dentry so we can supply private data */ 2076 - dent = aafs_create("namespaces", S_IFDIR | 0755, dir, ns, NULL, NULL, 2077 - &ns_dir_inode_operations); 2042 + dent = aafs_create("namespaces", S_IFDIR | 0755, dir, 2043 + &ns->unconfined->label.count, 2044 + NULL, NULL, &ns_dir_inode_operations); 2078 2045 if (IS_ERR(dent)) 2079 2046 return PTR_ERR(dent); 2080 - aa_get_ns(ns); 2081 2047 ns_subns_dir(ns) = dent; 2082 2048 2083 2049 return 0;
+8 -8
security/apparmor/include/label.h
··· 102 102 103 103 struct aa_label; 104 104 struct aa_proxy { 105 - struct kref count; 105 + struct aa_common_ref count; 106 106 struct aa_label __rcu *label; 107 107 }; 108 108 ··· 125 125 * vec: vector of profiles comprising the compound label 126 126 */ 127 127 struct aa_label { 128 - struct kref count; 128 + struct aa_common_ref count; 129 129 struct rb_node node; 130 130 struct rcu_head rcu; 131 131 struct aa_proxy *proxy; ··· 357 357 */ 358 358 static inline struct aa_label *__aa_get_label(struct aa_label *l) 359 359 { 360 - if (l && kref_get_unless_zero(&l->count)) 360 + if (l && kref_get_unless_zero(&l->count.count)) 361 361 return l; 362 362 363 363 return NULL; ··· 366 366 static inline struct aa_label *aa_get_label(struct aa_label *l) 367 367 { 368 368 if (l) 369 - kref_get(&(l->count)); 369 + kref_get(&(l->count.count)); 370 370 371 371 return l; 372 372 } ··· 386 386 rcu_read_lock(); 387 387 do { 388 388 c = rcu_dereference(*l); 389 - } while (c && !kref_get_unless_zero(&c->count)); 389 + } while (c && !kref_get_unless_zero(&c->count.count)); 390 390 rcu_read_unlock(); 391 391 392 392 return c; ··· 426 426 static inline void aa_put_label(struct aa_label *l) 427 427 { 428 428 if (l) 429 - kref_put(&l->count, aa_label_kref); 429 + kref_put(&l->count.count, aa_label_kref); 430 430 } 431 431 432 432 /* wrapper fn to indicate semantics of the check */ ··· 443 443 static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *proxy) 444 444 { 445 445 if (proxy) 446 - kref_get(&(proxy->count)); 446 + kref_get(&(proxy->count.count)); 447 447 448 448 return proxy; 449 449 } ··· 451 451 static inline void aa_put_proxy(struct aa_proxy *proxy) 452 452 { 453 453 if (proxy) 454 - kref_put(&proxy->count, aa_proxy_kref); 454 + kref_put(&proxy->count.count, aa_proxy_kref); 455 455 } 456 456 457 457 void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new);
+12
security/apparmor/include/lib.h
··· 102 102 /* Security blob offsets */ 103 103 extern struct lsm_blob_sizes apparmor_blob_sizes; 104 104 105 + enum reftype { 106 + REF_NS, 107 + REF_PROXY, 108 + REF_RAWDATA, 109 + }; 110 + 111 + /* common reference count used by data the shows up in aafs */ 112 + struct aa_common_ref { 113 + struct kref count; 114 + enum reftype reftype; 115 + }; 116 + 105 117 /** 106 118 * aa_strneq - compare null terminated @str to a non null terminated substring 107 119 * @str: a null terminated string
+4 -4
security/apparmor/include/policy.h
··· 379 379 static inline struct aa_profile *aa_get_profile(struct aa_profile *p) 380 380 { 381 381 if (p) 382 - kref_get(&(p->label.count)); 382 + kref_get(&(p->label.count.count)); 383 383 384 384 return p; 385 385 } ··· 393 393 */ 394 394 static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) 395 395 { 396 - if (p && kref_get_unless_zero(&p->label.count)) 396 + if (p && kref_get_unless_zero(&p->label.count.count)) 397 397 return p; 398 398 399 399 return NULL; ··· 413 413 rcu_read_lock(); 414 414 do { 415 415 c = rcu_dereference(*p); 416 - } while (c && !kref_get_unless_zero(&c->label.count)); 416 + } while (c && !kref_get_unless_zero(&c->label.count.count)); 417 417 rcu_read_unlock(); 418 418 419 419 return c; ··· 426 426 static inline void aa_put_profile(struct aa_profile *p) 427 427 { 428 428 if (p) 429 - kref_put(&p->label.count, aa_label_kref); 429 + kref_put(&p->label.count.count, aa_label_kref); 430 430 } 431 431 432 432 static inline int AUDIT_MODE(struct aa_profile *profile)
+3 -3
security/apparmor/include/policy_unpack.h
··· 108 108 * fs entries and drops the associated @count ref. 109 109 */ 110 110 struct aa_loaddata { 111 - struct kref count; 111 + struct aa_common_ref count; 112 112 struct kref pcount; 113 113 struct list_head list; 114 114 struct work_struct work; ··· 143 143 { 144 144 145 145 if (data) 146 - kref_get(&(data->count)); 146 + kref_get(&(data->count.count)); 147 147 return data; 148 148 } 149 149 ··· 171 171 static inline void aa_put_i_loaddata(struct aa_loaddata *data) 172 172 { 173 173 if (data) 174 - kref_put(&data->count, aa_loaddata_kref); 174 + kref_put(&data->count.count, aa_loaddata_kref); 175 175 } 176 176 177 177 static inline void aa_put_profile_loaddata(struct aa_loaddata *data)
+8 -4
security/apparmor/label.c
··· 52 52 53 53 void aa_proxy_kref(struct kref *kref) 54 54 { 55 - struct aa_proxy *proxy = container_of(kref, struct aa_proxy, count); 55 + struct aa_proxy *proxy = container_of(kref, struct aa_proxy, 56 + count.count); 56 57 57 58 free_proxy(proxy); 58 59 } ··· 64 63 65 64 new = kzalloc_obj(struct aa_proxy, gfp); 66 65 if (new) { 67 - kref_init(&new->count); 66 + kref_init(&new->count.count); 67 + new->count.reftype = REF_PROXY; 68 68 rcu_assign_pointer(new->label, aa_get_label(label)); 69 69 } 70 70 return new; ··· 377 375 378 376 void aa_label_kref(struct kref *kref) 379 377 { 380 - struct aa_label *label = container_of(kref, struct aa_label, count); 378 + struct aa_label *label = container_of(kref, struct aa_label, 379 + count.count); 381 380 struct aa_ns *ns = labels_ns(label); 382 381 383 382 if (!ns) { ··· 415 412 416 413 label->size = size; /* doesn't include null */ 417 414 label->vec[size] = NULL; /* null terminate */ 418 - kref_init(&label->count); 415 + kref_init(&label->count.count); 416 + label->count.reftype = REF_NS; /* for aafs purposes */ 419 417 RB_CLEAR_NODE(&label->node); 420 418 421 419 return true;
+4 -2
security/apparmor/policy_unpack.c
··· 119 119 120 120 void aa_loaddata_kref(struct kref *kref) 121 121 { 122 - struct aa_loaddata *d = container_of(kref, struct aa_loaddata, count); 122 + struct aa_loaddata *d = container_of(kref, struct aa_loaddata, 123 + count.count); 123 124 124 125 do_loaddata_free(d); 125 126 } ··· 167 166 kfree(d); 168 167 return ERR_PTR(-ENOMEM); 169 168 } 170 - kref_init(&d->count); 169 + kref_init(&d->count.count); 170 + d->count.reftype = REF_RAWDATA; 171 171 kref_init(&d->pcount); 172 172 INIT_LIST_HEAD(&d->list); 173 173