diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 320 |
1 files changed, 210 insertions, 110 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 6593a5207fb0..d1eab1d4a930 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -631,9 +631,8 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
631 | need_sid = 0; | 631 | need_sid = 0; |
632 | } | 632 | } |
633 | result = security_audit_rule_match(sid, f->type, | 633 | result = security_audit_rule_match(sid, f->type, |
634 | f->op, | 634 | f->op, |
635 | f->lsm_rule, | 635 | f->lsm_rule); |
636 | ctx); | ||
637 | } | 636 | } |
638 | break; | 637 | break; |
639 | case AUDIT_OBJ_USER: | 638 | case AUDIT_OBJ_USER: |
@@ -647,13 +646,17 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
647 | /* Find files that match */ | 646 | /* Find files that match */ |
648 | if (name) { | 647 | if (name) { |
649 | result = security_audit_rule_match( | 648 | result = security_audit_rule_match( |
650 | name->osid, f->type, f->op, | 649 | name->osid, |
651 | f->lsm_rule, ctx); | 650 | f->type, |
651 | f->op, | ||
652 | f->lsm_rule); | ||
652 | } else if (ctx) { | 653 | } else if (ctx) { |
653 | list_for_each_entry(n, &ctx->names_list, list) { | 654 | list_for_each_entry(n, &ctx->names_list, list) { |
654 | if (security_audit_rule_match(n->osid, f->type, | 655 | if (security_audit_rule_match( |
655 | f->op, f->lsm_rule, | 656 | n->osid, |
656 | ctx)) { | 657 | f->type, |
658 | f->op, | ||
659 | f->lsm_rule)) { | ||
657 | ++result; | 660 | ++result; |
658 | break; | 661 | break; |
659 | } | 662 | } |
@@ -664,7 +667,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
664 | break; | 667 | break; |
665 | if (security_audit_rule_match(ctx->ipc.osid, | 668 | if (security_audit_rule_match(ctx->ipc.osid, |
666 | f->type, f->op, | 669 | f->type, f->op, |
667 | f->lsm_rule, ctx)) | 670 | f->lsm_rule)) |
668 | ++result; | 671 | ++result; |
669 | } | 672 | } |
670 | break; | 673 | break; |
@@ -1136,6 +1139,32 @@ out: | |||
1136 | kfree(buf_head); | 1139 | kfree(buf_head); |
1137 | } | 1140 | } |
1138 | 1141 | ||
1142 | void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
1143 | { | ||
1144 | int i; | ||
1145 | |||
1146 | if (cap_isclear(*cap)) { | ||
1147 | audit_log_format(ab, " %s=0", prefix); | ||
1148 | return; | ||
1149 | } | ||
1150 | audit_log_format(ab, " %s=", prefix); | ||
1151 | CAP_FOR_EACH_U32(i) | ||
1152 | audit_log_format(ab, "%08x", cap->cap[CAP_LAST_U32 - i]); | ||
1153 | } | ||
1154 | |||
1155 | static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
1156 | { | ||
1157 | if (name->fcap_ver == -1) { | ||
1158 | audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?"); | ||
1159 | return; | ||
1160 | } | ||
1161 | audit_log_cap(ab, "cap_fp", &name->fcap.permitted); | ||
1162 | audit_log_cap(ab, "cap_fi", &name->fcap.inheritable); | ||
1163 | audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d", | ||
1164 | name->fcap.fE, name->fcap_ver, | ||
1165 | from_kuid(&init_user_ns, name->fcap.rootid)); | ||
1166 | } | ||
1167 | |||
1139 | static void show_special(struct audit_context *context, int *call_panic) | 1168 | static void show_special(struct audit_context *context, int *call_panic) |
1140 | { | 1169 | { |
1141 | struct audit_buffer *ab; | 1170 | struct audit_buffer *ab; |
@@ -1258,6 +1287,97 @@ static inline int audit_proctitle_rtrim(char *proctitle, int len) | |||
1258 | return len; | 1287 | return len; |
1259 | } | 1288 | } |
1260 | 1289 | ||
1290 | /* | ||
1291 | * audit_log_name - produce AUDIT_PATH record from struct audit_names | ||
1292 | * @context: audit_context for the task | ||
1293 | * @n: audit_names structure with reportable details | ||
1294 | * @path: optional path to report instead of audit_names->name | ||
1295 | * @record_num: record number to report when handling a list of names | ||
1296 | * @call_panic: optional pointer to int that will be updated if secid fails | ||
1297 | */ | ||
1298 | static void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
1299 | const struct path *path, int record_num, int *call_panic) | ||
1300 | { | ||
1301 | struct audit_buffer *ab; | ||
1302 | |||
1303 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
1304 | if (!ab) | ||
1305 | return; | ||
1306 | |||
1307 | audit_log_format(ab, "item=%d", record_num); | ||
1308 | |||
1309 | if (path) | ||
1310 | audit_log_d_path(ab, " name=", path); | ||
1311 | else if (n->name) { | ||
1312 | switch (n->name_len) { | ||
1313 | case AUDIT_NAME_FULL: | ||
1314 | /* log the full path */ | ||
1315 | audit_log_format(ab, " name="); | ||
1316 | audit_log_untrustedstring(ab, n->name->name); | ||
1317 | break; | ||
1318 | case 0: | ||
1319 | /* name was specified as a relative path and the | ||
1320 | * directory component is the cwd | ||
1321 | */ | ||
1322 | audit_log_d_path(ab, " name=", &context->pwd); | ||
1323 | break; | ||
1324 | default: | ||
1325 | /* log the name's directory component */ | ||
1326 | audit_log_format(ab, " name="); | ||
1327 | audit_log_n_untrustedstring(ab, n->name->name, | ||
1328 | n->name_len); | ||
1329 | } | ||
1330 | } else | ||
1331 | audit_log_format(ab, " name=(null)"); | ||
1332 | |||
1333 | if (n->ino != AUDIT_INO_UNSET) | ||
1334 | audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x", | ||
1335 | n->ino, | ||
1336 | MAJOR(n->dev), | ||
1337 | MINOR(n->dev), | ||
1338 | n->mode, | ||
1339 | from_kuid(&init_user_ns, n->uid), | ||
1340 | from_kgid(&init_user_ns, n->gid), | ||
1341 | MAJOR(n->rdev), | ||
1342 | MINOR(n->rdev)); | ||
1343 | if (n->osid != 0) { | ||
1344 | char *ctx = NULL; | ||
1345 | u32 len; | ||
1346 | |||
1347 | if (security_secid_to_secctx( | ||
1348 | n->osid, &ctx, &len)) { | ||
1349 | audit_log_format(ab, " osid=%u", n->osid); | ||
1350 | if (call_panic) | ||
1351 | *call_panic = 2; | ||
1352 | } else { | ||
1353 | audit_log_format(ab, " obj=%s", ctx); | ||
1354 | security_release_secctx(ctx, len); | ||
1355 | } | ||
1356 | } | ||
1357 | |||
1358 | /* log the audit_names record type */ | ||
1359 | switch (n->type) { | ||
1360 | case AUDIT_TYPE_NORMAL: | ||
1361 | audit_log_format(ab, " nametype=NORMAL"); | ||
1362 | break; | ||
1363 | case AUDIT_TYPE_PARENT: | ||
1364 | audit_log_format(ab, " nametype=PARENT"); | ||
1365 | break; | ||
1366 | case AUDIT_TYPE_CHILD_DELETE: | ||
1367 | audit_log_format(ab, " nametype=DELETE"); | ||
1368 | break; | ||
1369 | case AUDIT_TYPE_CHILD_CREATE: | ||
1370 | audit_log_format(ab, " nametype=CREATE"); | ||
1371 | break; | ||
1372 | default: | ||
1373 | audit_log_format(ab, " nametype=UNKNOWN"); | ||
1374 | break; | ||
1375 | } | ||
1376 | |||
1377 | audit_log_fcaps(ab, n); | ||
1378 | audit_log_end(ab); | ||
1379 | } | ||
1380 | |||
1261 | static void audit_log_proctitle(void) | 1381 | static void audit_log_proctitle(void) |
1262 | { | 1382 | { |
1263 | int res; | 1383 | int res; |
@@ -1358,6 +1478,9 @@ static void audit_log_exit(void) | |||
1358 | audit_log_cap(ab, "pi", &axs->new_pcap.inheritable); | 1478 | audit_log_cap(ab, "pi", &axs->new_pcap.inheritable); |
1359 | audit_log_cap(ab, "pe", &axs->new_pcap.effective); | 1479 | audit_log_cap(ab, "pe", &axs->new_pcap.effective); |
1360 | audit_log_cap(ab, "pa", &axs->new_pcap.ambient); | 1480 | audit_log_cap(ab, "pa", &axs->new_pcap.ambient); |
1481 | audit_log_format(ab, " frootid=%d", | ||
1482 | from_kuid(&init_user_ns, | ||
1483 | axs->fcap.rootid)); | ||
1361 | break; } | 1484 | break; } |
1362 | 1485 | ||
1363 | } | 1486 | } |
@@ -1444,6 +1567,9 @@ void __audit_free(struct task_struct *tsk) | |||
1444 | if (!context) | 1567 | if (!context) |
1445 | return; | 1568 | return; |
1446 | 1569 | ||
1570 | if (!list_empty(&context->killed_trees)) | ||
1571 | audit_kill_trees(context); | ||
1572 | |||
1447 | /* We are called either by do_exit() or the fork() error handling code; | 1573 | /* We are called either by do_exit() or the fork() error handling code; |
1448 | * in the former case tsk == current and in the latter tsk is a | 1574 | * in the former case tsk == current and in the latter tsk is a |
1449 | * random task_struct that doesn't doesn't have any meaningful data we | 1575 | * random task_struct that doesn't doesn't have any meaningful data we |
@@ -1460,9 +1586,6 @@ void __audit_free(struct task_struct *tsk) | |||
1460 | audit_log_exit(); | 1586 | audit_log_exit(); |
1461 | } | 1587 | } |
1462 | 1588 | ||
1463 | if (!list_empty(&context->killed_trees)) | ||
1464 | audit_kill_trees(&context->killed_trees); | ||
1465 | |||
1466 | audit_set_context(tsk, NULL); | 1589 | audit_set_context(tsk, NULL); |
1467 | audit_free_context(context); | 1590 | audit_free_context(context); |
1468 | } | 1591 | } |
@@ -1537,6 +1660,9 @@ void __audit_syscall_exit(int success, long return_code) | |||
1537 | if (!context) | 1660 | if (!context) |
1538 | return; | 1661 | return; |
1539 | 1662 | ||
1663 | if (!list_empty(&context->killed_trees)) | ||
1664 | audit_kill_trees(context); | ||
1665 | |||
1540 | if (!context->dummy && context->in_syscall) { | 1666 | if (!context->dummy && context->in_syscall) { |
1541 | if (success) | 1667 | if (success) |
1542 | context->return_valid = AUDITSC_SUCCESS; | 1668 | context->return_valid = AUDITSC_SUCCESS; |
@@ -1571,9 +1697,6 @@ void __audit_syscall_exit(int success, long return_code) | |||
1571 | context->in_syscall = 0; | 1697 | context->in_syscall = 0; |
1572 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; | 1698 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; |
1573 | 1699 | ||
1574 | if (!list_empty(&context->killed_trees)) | ||
1575 | audit_kill_trees(&context->killed_trees); | ||
1576 | |||
1577 | audit_free_names(context); | 1700 | audit_free_names(context); |
1578 | unroll_tree_refs(context, NULL, 0); | 1701 | unroll_tree_refs(context, NULL, 0); |
1579 | audit_free_aux(context); | 1702 | audit_free_aux(context); |
@@ -1750,6 +1873,47 @@ void __audit_getname(struct filename *name) | |||
1750 | get_fs_pwd(current->fs, &context->pwd); | 1873 | get_fs_pwd(current->fs, &context->pwd); |
1751 | } | 1874 | } |
1752 | 1875 | ||
1876 | static inline int audit_copy_fcaps(struct audit_names *name, | ||
1877 | const struct dentry *dentry) | ||
1878 | { | ||
1879 | struct cpu_vfs_cap_data caps; | ||
1880 | int rc; | ||
1881 | |||
1882 | if (!dentry) | ||
1883 | return 0; | ||
1884 | |||
1885 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
1886 | if (rc) | ||
1887 | return rc; | ||
1888 | |||
1889 | name->fcap.permitted = caps.permitted; | ||
1890 | name->fcap.inheritable = caps.inheritable; | ||
1891 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
1892 | name->fcap.rootid = caps.rootid; | ||
1893 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> | ||
1894 | VFS_CAP_REVISION_SHIFT; | ||
1895 | |||
1896 | return 0; | ||
1897 | } | ||
1898 | |||
1899 | /* Copy inode data into an audit_names. */ | ||
1900 | void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
1901 | struct inode *inode, unsigned int flags) | ||
1902 | { | ||
1903 | name->ino = inode->i_ino; | ||
1904 | name->dev = inode->i_sb->s_dev; | ||
1905 | name->mode = inode->i_mode; | ||
1906 | name->uid = inode->i_uid; | ||
1907 | name->gid = inode->i_gid; | ||
1908 | name->rdev = inode->i_rdev; | ||
1909 | security_inode_getsecid(inode, &name->osid); | ||
1910 | if (flags & AUDIT_INODE_NOEVAL) { | ||
1911 | name->fcap_ver = -1; | ||
1912 | return; | ||
1913 | } | ||
1914 | audit_copy_fcaps(name, dentry); | ||
1915 | } | ||
1916 | |||
1753 | /** | 1917 | /** |
1754 | * __audit_inode - store the inode and device from a lookup | 1918 | * __audit_inode - store the inode and device from a lookup |
1755 | * @name: name being audited | 1919 | * @name: name being audited |
@@ -1763,10 +1927,31 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
1763 | struct inode *inode = d_backing_inode(dentry); | 1927 | struct inode *inode = d_backing_inode(dentry); |
1764 | struct audit_names *n; | 1928 | struct audit_names *n; |
1765 | bool parent = flags & AUDIT_INODE_PARENT; | 1929 | bool parent = flags & AUDIT_INODE_PARENT; |
1930 | struct audit_entry *e; | ||
1931 | struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; | ||
1932 | int i; | ||
1766 | 1933 | ||
1767 | if (!context->in_syscall) | 1934 | if (!context->in_syscall) |
1768 | return; | 1935 | return; |
1769 | 1936 | ||
1937 | rcu_read_lock(); | ||
1938 | if (!list_empty(list)) { | ||
1939 | list_for_each_entry_rcu(e, list, list) { | ||
1940 | for (i = 0; i < e->rule.field_count; i++) { | ||
1941 | struct audit_field *f = &e->rule.fields[i]; | ||
1942 | |||
1943 | if (f->type == AUDIT_FSTYPE | ||
1944 | && audit_comparator(inode->i_sb->s_magic, | ||
1945 | f->op, f->val) | ||
1946 | && e->rule.action == AUDIT_NEVER) { | ||
1947 | rcu_read_unlock(); | ||
1948 | return; | ||
1949 | } | ||
1950 | } | ||
1951 | } | ||
1952 | } | ||
1953 | rcu_read_unlock(); | ||
1954 | |||
1770 | if (!name) | 1955 | if (!name) |
1771 | goto out_alloc; | 1956 | goto out_alloc; |
1772 | 1957 | ||
@@ -1832,7 +2017,7 @@ out: | |||
1832 | n->type = AUDIT_TYPE_NORMAL; | 2017 | n->type = AUDIT_TYPE_NORMAL; |
1833 | } | 2018 | } |
1834 | handle_path(dentry); | 2019 | handle_path(dentry); |
1835 | audit_copy_inode(n, dentry, inode); | 2020 | audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL); |
1836 | } | 2021 | } |
1837 | 2022 | ||
1838 | void __audit_file(const struct file *file) | 2023 | void __audit_file(const struct file *file) |
@@ -1875,14 +2060,12 @@ void __audit_inode_child(struct inode *parent, | |||
1875 | for (i = 0; i < e->rule.field_count; i++) { | 2060 | for (i = 0; i < e->rule.field_count; i++) { |
1876 | struct audit_field *f = &e->rule.fields[i]; | 2061 | struct audit_field *f = &e->rule.fields[i]; |
1877 | 2062 | ||
1878 | if (f->type == AUDIT_FSTYPE) { | 2063 | if (f->type == AUDIT_FSTYPE |
1879 | if (audit_comparator(parent->i_sb->s_magic, | 2064 | && audit_comparator(parent->i_sb->s_magic, |
1880 | f->op, f->val)) { | 2065 | f->op, f->val) |
1881 | if (e->rule.action == AUDIT_NEVER) { | 2066 | && e->rule.action == AUDIT_NEVER) { |
1882 | rcu_read_unlock(); | 2067 | rcu_read_unlock(); |
1883 | return; | 2068 | return; |
1884 | } | ||
1885 | } | ||
1886 | } | 2069 | } |
1887 | } | 2070 | } |
1888 | } | 2071 | } |
@@ -1933,7 +2116,7 @@ void __audit_inode_child(struct inode *parent, | |||
1933 | n = audit_alloc_name(context, AUDIT_TYPE_PARENT); | 2116 | n = audit_alloc_name(context, AUDIT_TYPE_PARENT); |
1934 | if (!n) | 2117 | if (!n) |
1935 | return; | 2118 | return; |
1936 | audit_copy_inode(n, NULL, parent); | 2119 | audit_copy_inode(n, NULL, parent, 0); |
1937 | } | 2120 | } |
1938 | 2121 | ||
1939 | if (!found_child) { | 2122 | if (!found_child) { |
@@ -1952,7 +2135,7 @@ void __audit_inode_child(struct inode *parent, | |||
1952 | } | 2135 | } |
1953 | 2136 | ||
1954 | if (inode) | 2137 | if (inode) |
1955 | audit_copy_inode(found_child, dentry, inode); | 2138 | audit_copy_inode(found_child, dentry, inode, 0); |
1956 | else | 2139 | else |
1957 | found_child->ino = AUDIT_INO_UNSET; | 2140 | found_child->ino = AUDIT_INO_UNSET; |
1958 | } | 2141 | } |
@@ -1983,90 +2166,6 @@ int auditsc_get_stamp(struct audit_context *ctx, | |||
1983 | return 1; | 2166 | return 1; |
1984 | } | 2167 | } |
1985 | 2168 | ||
1986 | /* global counter which is incremented every time something logs in */ | ||
1987 | static atomic_t session_id = ATOMIC_INIT(0); | ||
1988 | |||
1989 | static int audit_set_loginuid_perm(kuid_t loginuid) | ||
1990 | { | ||
1991 | /* if we are unset, we don't need privs */ | ||
1992 | if (!audit_loginuid_set(current)) | ||
1993 | return 0; | ||
1994 | /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ | ||
1995 | if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) | ||
1996 | return -EPERM; | ||
1997 | /* it is set, you need permission */ | ||
1998 | if (!capable(CAP_AUDIT_CONTROL)) | ||
1999 | return -EPERM; | ||
2000 | /* reject if this is not an unset and we don't allow that */ | ||
2001 | if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid)) | ||
2002 | return -EPERM; | ||
2003 | return 0; | ||
2004 | } | ||
2005 | |||
2006 | static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | ||
2007 | unsigned int oldsessionid, unsigned int sessionid, | ||
2008 | int rc) | ||
2009 | { | ||
2010 | struct audit_buffer *ab; | ||
2011 | uid_t uid, oldloginuid, loginuid; | ||
2012 | struct tty_struct *tty; | ||
2013 | |||
2014 | if (!audit_enabled) | ||
2015 | return; | ||
2016 | |||
2017 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | ||
2018 | if (!ab) | ||
2019 | return; | ||
2020 | |||
2021 | uid = from_kuid(&init_user_ns, task_uid(current)); | ||
2022 | oldloginuid = from_kuid(&init_user_ns, koldloginuid); | ||
2023 | loginuid = from_kuid(&init_user_ns, kloginuid), | ||
2024 | tty = audit_get_tty(); | ||
2025 | |||
2026 | audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); | ||
2027 | audit_log_task_context(ab); | ||
2028 | audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", | ||
2029 | oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", | ||
2030 | oldsessionid, sessionid, !rc); | ||
2031 | audit_put_tty(tty); | ||
2032 | audit_log_end(ab); | ||
2033 | } | ||
2034 | |||
2035 | /** | ||
2036 | * audit_set_loginuid - set current task's audit_context loginuid | ||
2037 | * @loginuid: loginuid value | ||
2038 | * | ||
2039 | * Returns 0. | ||
2040 | * | ||
2041 | * Called (set) from fs/proc/base.c::proc_loginuid_write(). | ||
2042 | */ | ||
2043 | int audit_set_loginuid(kuid_t loginuid) | ||
2044 | { | ||
2045 | unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; | ||
2046 | kuid_t oldloginuid; | ||
2047 | int rc; | ||
2048 | |||
2049 | oldloginuid = audit_get_loginuid(current); | ||
2050 | oldsessionid = audit_get_sessionid(current); | ||
2051 | |||
2052 | rc = audit_set_loginuid_perm(loginuid); | ||
2053 | if (rc) | ||
2054 | goto out; | ||
2055 | |||
2056 | /* are we setting or clearing? */ | ||
2057 | if (uid_valid(loginuid)) { | ||
2058 | sessionid = (unsigned int)atomic_inc_return(&session_id); | ||
2059 | if (unlikely(sessionid == AUDIT_SID_UNSET)) | ||
2060 | sessionid = (unsigned int)atomic_inc_return(&session_id); | ||
2061 | } | ||
2062 | |||
2063 | current->sessionid = sessionid; | ||
2064 | current->loginuid = loginuid; | ||
2065 | out: | ||
2066 | audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); | ||
2067 | return rc; | ||
2068 | } | ||
2069 | |||
2070 | /** | 2169 | /** |
2071 | * __audit_mq_open - record audit data for a POSIX MQ open | 2170 | * __audit_mq_open - record audit data for a POSIX MQ open |
2072 | * @oflag: open flag | 2171 | * @oflag: open flag |
@@ -2355,6 +2454,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, | |||
2355 | ax->fcap.permitted = vcaps.permitted; | 2454 | ax->fcap.permitted = vcaps.permitted; |
2356 | ax->fcap.inheritable = vcaps.inheritable; | 2455 | ax->fcap.inheritable = vcaps.inheritable; |
2357 | ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | 2456 | ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); |
2457 | ax->fcap.rootid = vcaps.rootid; | ||
2358 | ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; | 2458 | ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; |
2359 | 2459 | ||
2360 | ax->old_pcap.permitted = old->cap_permitted; | 2460 | ax->old_pcap.permitted = old->cap_permitted; |