18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/attr.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 68c2ecf20Sopenharmony_ci * changes by Thomas Schoebel-Theuer 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/export.h> 108c2ecf20Sopenharmony_ci#include <linux/time.h> 118c2ecf20Sopenharmony_ci#include <linux/mm.h> 128c2ecf20Sopenharmony_ci#include <linux/string.h> 138c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 148c2ecf20Sopenharmony_ci#include <linux/capability.h> 158c2ecf20Sopenharmony_ci#include <linux/fsnotify.h> 168c2ecf20Sopenharmony_ci#include <linux/fcntl.h> 178c2ecf20Sopenharmony_ci#include <linux/security.h> 188c2ecf20Sopenharmony_ci#include <linux/evm.h> 198c2ecf20Sopenharmony_ci#include <linux/ima.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "internal.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/** 248c2ecf20Sopenharmony_ci * setattr_should_drop_sgid - determine whether the setgid bit needs to be 258c2ecf20Sopenharmony_ci * removed 268c2ecf20Sopenharmony_ci * @inode: inode to check 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * This function determines whether the setgid bit needs to be removed. 298c2ecf20Sopenharmony_ci * We retain backwards compatibility and require setgid bit to be removed 308c2ecf20Sopenharmony_ci * unconditionally if S_IXGRP is set. Otherwise we have the exact same 318c2ecf20Sopenharmony_ci * requirements as setattr_prepare() and setattr_copy(). 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * Return: ATTR_KILL_SGID if setgid bit needs to be removed, 0 otherwise. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ciint setattr_should_drop_sgid(const struct inode *inode) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci umode_t mode = inode->i_mode; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci if (!(mode & S_ISGID)) 408c2ecf20Sopenharmony_ci return 0; 418c2ecf20Sopenharmony_ci if (mode & S_IXGRP) 428c2ecf20Sopenharmony_ci return ATTR_KILL_SGID; 438c2ecf20Sopenharmony_ci if (!in_group_or_capable(inode, inode->i_gid)) 448c2ecf20Sopenharmony_ci return ATTR_KILL_SGID; 458c2ecf20Sopenharmony_ci return 0; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/** 498c2ecf20Sopenharmony_ci * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to 508c2ecf20Sopenharmony_ci * be dropped 518c2ecf20Sopenharmony_ci * @inode: inode to check 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * This function determines whether the set{g,u}id bits need to be removed. 548c2ecf20Sopenharmony_ci * If the setuid bit needs to be removed ATTR_KILL_SUID is returned. If the 558c2ecf20Sopenharmony_ci * setgid bit needs to be removed ATTR_KILL_SGID is returned. If both 568c2ecf20Sopenharmony_ci * set{g,u}id bits need to be removed the corresponding mask of both flags is 578c2ecf20Sopenharmony_ci * returned. 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Return: A mask of ATTR_KILL_S{G,U}ID indicating which - if any - setid bits 608c2ecf20Sopenharmony_ci * to remove, 0 otherwise. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ciint setattr_should_drop_suidgid(struct inode *inode) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci umode_t mode = inode->i_mode; 658c2ecf20Sopenharmony_ci int kill = 0; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* suid always must be killed */ 688c2ecf20Sopenharmony_ci if (unlikely(mode & S_ISUID)) 698c2ecf20Sopenharmony_ci kill = ATTR_KILL_SUID; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci kill |= setattr_should_drop_sgid(inode); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode))) 748c2ecf20Sopenharmony_ci return kill; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return 0; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(setattr_should_drop_suidgid); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic bool chown_ok(const struct inode *inode, kuid_t uid) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci if (uid_eq(current_fsuid(), inode->i_uid) && 838c2ecf20Sopenharmony_ci uid_eq(uid, inode->i_uid)) 848c2ecf20Sopenharmony_ci return true; 858c2ecf20Sopenharmony_ci if (capable_wrt_inode_uidgid(inode, CAP_CHOWN)) 868c2ecf20Sopenharmony_ci return true; 878c2ecf20Sopenharmony_ci if (uid_eq(inode->i_uid, INVALID_UID) && 888c2ecf20Sopenharmony_ci ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN)) 898c2ecf20Sopenharmony_ci return true; 908c2ecf20Sopenharmony_ci return false; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic bool chgrp_ok(const struct inode *inode, kgid_t gid) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci if (uid_eq(current_fsuid(), inode->i_uid) && 968c2ecf20Sopenharmony_ci (in_group_p(gid) || gid_eq(gid, inode->i_gid))) 978c2ecf20Sopenharmony_ci return true; 988c2ecf20Sopenharmony_ci if (capable_wrt_inode_uidgid(inode, CAP_CHOWN)) 998c2ecf20Sopenharmony_ci return true; 1008c2ecf20Sopenharmony_ci if (gid_eq(inode->i_gid, INVALID_GID) && 1018c2ecf20Sopenharmony_ci ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN)) 1028c2ecf20Sopenharmony_ci return true; 1038c2ecf20Sopenharmony_ci return false; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/** 1078c2ecf20Sopenharmony_ci * setattr_prepare - check if attribute changes to a dentry are allowed 1088c2ecf20Sopenharmony_ci * @dentry: dentry to check 1098c2ecf20Sopenharmony_ci * @attr: attributes to change 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * Check if we are allowed to change the attributes contained in @attr 1128c2ecf20Sopenharmony_ci * in the given dentry. This includes the normal unix access permission 1138c2ecf20Sopenharmony_ci * checks, as well as checks for rlimits and others. The function also clears 1148c2ecf20Sopenharmony_ci * SGID bit from mode if user is not allowed to set it. Also file capabilities 1158c2ecf20Sopenharmony_ci * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set. 1168c2ecf20Sopenharmony_ci * 1178c2ecf20Sopenharmony_ci * Should be called as the first thing in ->setattr implementations, 1188c2ecf20Sopenharmony_ci * possibly after taking additional locks. 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ciint setattr_prepare(struct dentry *dentry, struct iattr *attr) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 1238c2ecf20Sopenharmony_ci unsigned int ia_valid = attr->ia_valid; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* 1268c2ecf20Sopenharmony_ci * First check size constraints. These can't be overriden using 1278c2ecf20Sopenharmony_ci * ATTR_FORCE. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci if (ia_valid & ATTR_SIZE) { 1308c2ecf20Sopenharmony_ci int error = inode_newsize_ok(inode, attr->ia_size); 1318c2ecf20Sopenharmony_ci if (error) 1328c2ecf20Sopenharmony_ci return error; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* If force is set do it anyway. */ 1368c2ecf20Sopenharmony_ci if (ia_valid & ATTR_FORCE) 1378c2ecf20Sopenharmony_ci goto kill_priv; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* Make sure a caller can chown. */ 1408c2ecf20Sopenharmony_ci if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid)) 1418c2ecf20Sopenharmony_ci return -EPERM; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* Make sure caller can chgrp. */ 1448c2ecf20Sopenharmony_ci if ((ia_valid & ATTR_GID) && !chgrp_ok(inode, attr->ia_gid)) 1458c2ecf20Sopenharmony_ci return -EPERM; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* Make sure a caller can chmod. */ 1488c2ecf20Sopenharmony_ci if (ia_valid & ATTR_MODE) { 1498c2ecf20Sopenharmony_ci if (!inode_owner_or_capable(inode)) 1508c2ecf20Sopenharmony_ci return -EPERM; 1518c2ecf20Sopenharmony_ci /* Also check the setgid bit! */ 1528c2ecf20Sopenharmony_ci if (!in_group_or_capable(inode, (ia_valid & ATTR_GID) ? 1538c2ecf20Sopenharmony_ci attr->ia_gid : inode->i_gid)) 1548c2ecf20Sopenharmony_ci attr->ia_mode &= ~S_ISGID; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Check for setting the inode time. */ 1588c2ecf20Sopenharmony_ci if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) { 1598c2ecf20Sopenharmony_ci if (!inode_owner_or_capable(inode)) 1608c2ecf20Sopenharmony_ci return -EPERM; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cikill_priv: 1648c2ecf20Sopenharmony_ci /* User has permission for the change */ 1658c2ecf20Sopenharmony_ci if (ia_valid & ATTR_KILL_PRIV) { 1668c2ecf20Sopenharmony_ci int error; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci error = security_inode_killpriv(dentry); 1698c2ecf20Sopenharmony_ci if (error) 1708c2ecf20Sopenharmony_ci return error; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci return 0; 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(setattr_prepare); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/** 1788c2ecf20Sopenharmony_ci * inode_newsize_ok - may this inode be truncated to a given size 1798c2ecf20Sopenharmony_ci * @inode: the inode to be truncated 1808c2ecf20Sopenharmony_ci * @offset: the new size to assign to the inode 1818c2ecf20Sopenharmony_ci * 1828c2ecf20Sopenharmony_ci * inode_newsize_ok must be called with i_mutex held. 1838c2ecf20Sopenharmony_ci * 1848c2ecf20Sopenharmony_ci * inode_newsize_ok will check filesystem limits and ulimits to check that the 1858c2ecf20Sopenharmony_ci * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ 1868c2ecf20Sopenharmony_ci * when necessary. Caller must not proceed with inode size change if failure is 1878c2ecf20Sopenharmony_ci * returned. @inode must be a file (not directory), with appropriate 1888c2ecf20Sopenharmony_ci * permissions to allow truncate (inode_newsize_ok does NOT check these 1898c2ecf20Sopenharmony_ci * conditions). 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * Return: 0 on success, -ve errno on failure 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_ciint inode_newsize_ok(const struct inode *inode, loff_t offset) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci if (offset < 0) 1968c2ecf20Sopenharmony_ci return -EINVAL; 1978c2ecf20Sopenharmony_ci if (inode->i_size < offset) { 1988c2ecf20Sopenharmony_ci unsigned long limit; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci limit = rlimit(RLIMIT_FSIZE); 2018c2ecf20Sopenharmony_ci if (limit != RLIM_INFINITY && offset > limit) 2028c2ecf20Sopenharmony_ci goto out_sig; 2038c2ecf20Sopenharmony_ci if (offset > inode->i_sb->s_maxbytes) 2048c2ecf20Sopenharmony_ci goto out_big; 2058c2ecf20Sopenharmony_ci } else { 2068c2ecf20Sopenharmony_ci /* 2078c2ecf20Sopenharmony_ci * truncation of in-use swapfiles is disallowed - it would 2088c2ecf20Sopenharmony_ci * cause subsequent swapout to scribble on the now-freed 2098c2ecf20Sopenharmony_ci * blocks. 2108c2ecf20Sopenharmony_ci */ 2118c2ecf20Sopenharmony_ci if (IS_SWAPFILE(inode)) 2128c2ecf20Sopenharmony_ci return -ETXTBSY; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ciout_sig: 2178c2ecf20Sopenharmony_ci send_sig(SIGXFSZ, current, 0); 2188c2ecf20Sopenharmony_ciout_big: 2198c2ecf20Sopenharmony_ci return -EFBIG; 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(inode_newsize_ok); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/** 2248c2ecf20Sopenharmony_ci * setattr_copy - copy simple metadata updates into the generic inode 2258c2ecf20Sopenharmony_ci * @inode: the inode to be updated 2268c2ecf20Sopenharmony_ci * @attr: the new attributes 2278c2ecf20Sopenharmony_ci * 2288c2ecf20Sopenharmony_ci * setattr_copy must be called with i_mutex held. 2298c2ecf20Sopenharmony_ci * 2308c2ecf20Sopenharmony_ci * setattr_copy updates the inode's metadata with that specified 2318c2ecf20Sopenharmony_ci * in attr. Noticeably missing is inode size update, which is more complex 2328c2ecf20Sopenharmony_ci * as it requires pagecache updates. 2338c2ecf20Sopenharmony_ci * 2348c2ecf20Sopenharmony_ci * The inode is not marked as dirty after this operation. The rationale is 2358c2ecf20Sopenharmony_ci * that for "simple" filesystems, the struct inode is the inode storage. 2368c2ecf20Sopenharmony_ci * The caller is free to mark the inode dirty afterwards if needed. 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_civoid setattr_copy(struct inode *inode, const struct iattr *attr) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci unsigned int ia_valid = attr->ia_valid; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (ia_valid & ATTR_UID) 2438c2ecf20Sopenharmony_ci inode->i_uid = attr->ia_uid; 2448c2ecf20Sopenharmony_ci if (ia_valid & ATTR_GID) 2458c2ecf20Sopenharmony_ci inode->i_gid = attr->ia_gid; 2468c2ecf20Sopenharmony_ci if (ia_valid & ATTR_ATIME) 2478c2ecf20Sopenharmony_ci inode->i_atime = attr->ia_atime; 2488c2ecf20Sopenharmony_ci if (ia_valid & ATTR_MTIME) 2498c2ecf20Sopenharmony_ci inode->i_mtime = attr->ia_mtime; 2508c2ecf20Sopenharmony_ci if (ia_valid & ATTR_CTIME) 2518c2ecf20Sopenharmony_ci inode->i_ctime = attr->ia_ctime; 2528c2ecf20Sopenharmony_ci if (ia_valid & ATTR_MODE) { 2538c2ecf20Sopenharmony_ci umode_t mode = attr->ia_mode; 2548c2ecf20Sopenharmony_ci if (!in_group_or_capable(inode, inode->i_gid)) 2558c2ecf20Sopenharmony_ci mode &= ~S_ISGID; 2568c2ecf20Sopenharmony_ci inode->i_mode = mode; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(setattr_copy); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci/** 2628c2ecf20Sopenharmony_ci * notify_change - modify attributes of a filesytem object 2638c2ecf20Sopenharmony_ci * @dentry: object affected 2648c2ecf20Sopenharmony_ci * @attr: new attributes 2658c2ecf20Sopenharmony_ci * @delegated_inode: returns inode, if the inode is delegated 2668c2ecf20Sopenharmony_ci * 2678c2ecf20Sopenharmony_ci * The caller must hold the i_mutex on the affected object. 2688c2ecf20Sopenharmony_ci * 2698c2ecf20Sopenharmony_ci * If notify_change discovers a delegation in need of breaking, 2708c2ecf20Sopenharmony_ci * it will return -EWOULDBLOCK and return a reference to the inode in 2718c2ecf20Sopenharmony_ci * delegated_inode. The caller should then break the delegation and 2728c2ecf20Sopenharmony_ci * retry. Because breaking a delegation may take a long time, the 2738c2ecf20Sopenharmony_ci * caller should drop the i_mutex before doing so. 2748c2ecf20Sopenharmony_ci * 2758c2ecf20Sopenharmony_ci * Alternatively, a caller may pass NULL for delegated_inode. This may 2768c2ecf20Sopenharmony_ci * be appropriate for callers that expect the underlying filesystem not 2778c2ecf20Sopenharmony_ci * to be NFS exported. Also, passing NULL is fine for callers holding 2788c2ecf20Sopenharmony_ci * the file open for write, as there can be no conflicting delegation in 2798c2ecf20Sopenharmony_ci * that case. 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_ciint notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct inode *inode = dentry->d_inode; 2848c2ecf20Sopenharmony_ci umode_t mode = inode->i_mode; 2858c2ecf20Sopenharmony_ci int error; 2868c2ecf20Sopenharmony_ci struct timespec64 now; 2878c2ecf20Sopenharmony_ci unsigned int ia_valid = attr->ia_valid; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci WARN_ON_ONCE(!inode_is_locked(inode)); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) { 2928c2ecf20Sopenharmony_ci if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 2938c2ecf20Sopenharmony_ci return -EPERM; 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* 2978c2ecf20Sopenharmony_ci * If utimes(2) and friends are called with times == NULL (or both 2988c2ecf20Sopenharmony_ci * times are UTIME_NOW), then we need to check for write permission 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ci if (ia_valid & ATTR_TOUCH) { 3018c2ecf20Sopenharmony_ci if (IS_IMMUTABLE(inode)) 3028c2ecf20Sopenharmony_ci return -EPERM; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (!inode_owner_or_capable(inode)) { 3058c2ecf20Sopenharmony_ci error = inode_permission(inode, MAY_WRITE); 3068c2ecf20Sopenharmony_ci if (error) 3078c2ecf20Sopenharmony_ci return error; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if ((ia_valid & ATTR_MODE)) { 3128c2ecf20Sopenharmony_ci /* 3138c2ecf20Sopenharmony_ci * Don't allow changing the mode of symlinks: 3148c2ecf20Sopenharmony_ci * 3158c2ecf20Sopenharmony_ci * (1) The vfs doesn't take the mode of symlinks into account 3168c2ecf20Sopenharmony_ci * during permission checking. 3178c2ecf20Sopenharmony_ci * (2) This has never worked correctly. Most major filesystems 3188c2ecf20Sopenharmony_ci * did return EOPNOTSUPP due to interactions with POSIX ACLs 3198c2ecf20Sopenharmony_ci * but did still updated the mode of the symlink. 3208c2ecf20Sopenharmony_ci * This inconsistency led system call wrapper providers such 3218c2ecf20Sopenharmony_ci * as libc to block changing the mode of symlinks with 3228c2ecf20Sopenharmony_ci * EOPNOTSUPP already. 3238c2ecf20Sopenharmony_ci * (3) To even do this in the first place one would have to use 3248c2ecf20Sopenharmony_ci * specific file descriptors and quite some effort. 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 3278c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* Flag setting protected by i_mutex */ 3308c2ecf20Sopenharmony_ci if (is_sxid(attr->ia_mode)) 3318c2ecf20Sopenharmony_ci inode->i_flags &= ~S_NOSEC; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci now = current_time(inode); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci attr->ia_ctime = now; 3378c2ecf20Sopenharmony_ci if (!(ia_valid & ATTR_ATIME_SET)) 3388c2ecf20Sopenharmony_ci attr->ia_atime = now; 3398c2ecf20Sopenharmony_ci else 3408c2ecf20Sopenharmony_ci attr->ia_atime = timestamp_truncate(attr->ia_atime, inode); 3418c2ecf20Sopenharmony_ci if (!(ia_valid & ATTR_MTIME_SET)) 3428c2ecf20Sopenharmony_ci attr->ia_mtime = now; 3438c2ecf20Sopenharmony_ci else 3448c2ecf20Sopenharmony_ci attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (ia_valid & ATTR_KILL_PRIV) { 3478c2ecf20Sopenharmony_ci error = security_inode_need_killpriv(dentry); 3488c2ecf20Sopenharmony_ci if (error < 0) 3498c2ecf20Sopenharmony_ci return error; 3508c2ecf20Sopenharmony_ci if (error == 0) 3518c2ecf20Sopenharmony_ci ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* 3558c2ecf20Sopenharmony_ci * We now pass ATTR_KILL_S*ID to the lower level setattr function so 3568c2ecf20Sopenharmony_ci * that the function has the ability to reinterpret a mode change 3578c2ecf20Sopenharmony_ci * that's due to these bits. This adds an implicit restriction that 3588c2ecf20Sopenharmony_ci * no function will ever call notify_change with both ATTR_MODE and 3598c2ecf20Sopenharmony_ci * ATTR_KILL_S*ID set. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ci if ((ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) && 3628c2ecf20Sopenharmony_ci (ia_valid & ATTR_MODE)) 3638c2ecf20Sopenharmony_ci BUG(); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci if (ia_valid & ATTR_KILL_SUID) { 3668c2ecf20Sopenharmony_ci if (mode & S_ISUID) { 3678c2ecf20Sopenharmony_ci ia_valid = attr->ia_valid |= ATTR_MODE; 3688c2ecf20Sopenharmony_ci attr->ia_mode = (inode->i_mode & ~S_ISUID); 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci if (ia_valid & ATTR_KILL_SGID) { 3728c2ecf20Sopenharmony_ci if (mode & S_ISGID) { 3738c2ecf20Sopenharmony_ci if (!(ia_valid & ATTR_MODE)) { 3748c2ecf20Sopenharmony_ci ia_valid = attr->ia_valid |= ATTR_MODE; 3758c2ecf20Sopenharmony_ci attr->ia_mode = inode->i_mode; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci attr->ia_mode &= ~S_ISGID; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci if (!(attr->ia_valid & ~(ATTR_KILL_SUID | ATTR_KILL_SGID))) 3818c2ecf20Sopenharmony_ci return 0; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* 3848c2ecf20Sopenharmony_ci * Verify that uid/gid changes are valid in the target 3858c2ecf20Sopenharmony_ci * namespace of the superblock. 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_ci if (ia_valid & ATTR_UID && 3888c2ecf20Sopenharmony_ci !kuid_has_mapping(inode->i_sb->s_user_ns, attr->ia_uid)) 3898c2ecf20Sopenharmony_ci return -EOVERFLOW; 3908c2ecf20Sopenharmony_ci if (ia_valid & ATTR_GID && 3918c2ecf20Sopenharmony_ci !kgid_has_mapping(inode->i_sb->s_user_ns, attr->ia_gid)) 3928c2ecf20Sopenharmony_ci return -EOVERFLOW; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* Don't allow modifications of files with invalid uids or 3958c2ecf20Sopenharmony_ci * gids unless those uids & gids are being made valid. 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_ci if (!(ia_valid & ATTR_UID) && !uid_valid(inode->i_uid)) 3988c2ecf20Sopenharmony_ci return -EOVERFLOW; 3998c2ecf20Sopenharmony_ci if (!(ia_valid & ATTR_GID) && !gid_valid(inode->i_gid)) 4008c2ecf20Sopenharmony_ci return -EOVERFLOW; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci error = security_inode_setattr(dentry, attr); 4038c2ecf20Sopenharmony_ci if (error) 4048c2ecf20Sopenharmony_ci return error; 4058c2ecf20Sopenharmony_ci error = try_break_deleg(inode, delegated_inode); 4068c2ecf20Sopenharmony_ci if (error) 4078c2ecf20Sopenharmony_ci return error; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (inode->i_op->setattr) 4108c2ecf20Sopenharmony_ci error = inode->i_op->setattr(dentry, attr); 4118c2ecf20Sopenharmony_ci else 4128c2ecf20Sopenharmony_ci error = simple_setattr(dentry, attr); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (!error) { 4158c2ecf20Sopenharmony_ci fsnotify_change(dentry, ia_valid); 4168c2ecf20Sopenharmony_ci ima_inode_post_setattr(dentry); 4178c2ecf20Sopenharmony_ci evm_inode_post_setattr(dentry, ia_valid); 4188c2ecf20Sopenharmony_ci } 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci return error; 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(notify_change); 423