1 /* 2 * linux/fs/attr.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * changes by Thomas Schoebel-Theuer 6 */ 7 8 #include <linux/module.h> 9 #include <linux/time.h> 10 #include <linux/mm.h> 11 #include <linux/string.h> 12 #include <linux/smp_lock.h> 13 #include <linux/fsnotify.h> 14 #include <linux/fcntl.h> 15 #include <linux/quotaops.h> 16 #include <linux/security.h> 17 #include <linux/time.h> 18 19 /* Taken over from the old code... */ 20 21 /* POSIX UID/GID verification for setting inode attributes. */ 22 int inode_change_ok(struct inode *inode, struct iattr *attr) 23 { 24 int retval = -EPERM; 25 unsigned int ia_valid = attr->ia_valid; 26 27 /* If force is set do it anyway. */ 28 if (ia_valid & ATTR_FORCE) 29 goto fine; 30 31 /* Make sure a caller can chown. */ 32 if ((ia_valid & ATTR_UID) && 33 (current->fsuid != inode->i_uid || 34 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN)) 35 goto error; 36 37 /* Make sure caller can chgrp. */ 38 if ((ia_valid & ATTR_GID) && 39 (current->fsuid != inode->i_uid || 40 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) && 41 !capable(CAP_CHOWN)) 42 goto error; 43 44 /* Make sure a caller can chmod. */ 45 if (ia_valid & ATTR_MODE) { 46 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 47 goto error; 48 /* Also check the setgid bit! */ 49 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : 50 inode->i_gid) && !capable(CAP_FSETID)) 51 attr->ia_mode &= ~S_ISGID; 52 } 53 54 /* Check for setting the inode time. */ 55 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) { 56 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) 57 goto error; 58 } 59 fine: 60 retval = 0; 61 error: 62 return retval; 63 } 64 65 EXPORT_SYMBOL(inode_change_ok); 66 67 int inode_setattr(struct inode * inode, struct iattr * attr) 68 { 69 unsigned int ia_valid = attr->ia_valid; 70 71 if (ia_valid & ATTR_SIZE && 72 attr->ia_size != i_size_read(inode)) { 73 int error = vmtruncate(inode, attr->ia_size); 74 if (error) 75 return error; 76 } 77 78 if (ia_valid & ATTR_UID) 79 inode->i_uid = attr->ia_uid; 80 if (ia_valid & ATTR_GID) 81 inode->i_gid = attr->ia_gid; 82 if (ia_valid & ATTR_ATIME) 83 inode->i_atime = timespec_trunc(attr->ia_atime, 84 inode->i_sb->s_time_gran); 85 if (ia_valid & ATTR_MTIME) 86 inode->i_mtime = timespec_trunc(attr->ia_mtime, 87 inode->i_sb->s_time_gran); 88 if (ia_valid & ATTR_CTIME) 89 inode->i_ctime = timespec_trunc(attr->ia_ctime, 90 inode->i_sb->s_time_gran); 91 if (ia_valid & ATTR_MODE) { 92 umode_t mode = attr->ia_mode; 93 94 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 95 mode &= ~S_ISGID; 96 inode->i_mode = mode; 97 } 98 mark_inode_dirty(inode); 99 100 return 0; 101 } 102 EXPORT_SYMBOL(inode_setattr); 103 104 int notify_change(struct dentry * dentry, struct iattr * attr) 105 { 106 struct inode *inode = dentry->d_inode; 107 mode_t mode; 108 int error; 109 struct timespec now; 110 unsigned int ia_valid = attr->ia_valid; 111 112 mode = inode->i_mode; 113 now = current_fs_time(inode->i_sb); 114 115 attr->ia_ctime = now; 116 if (!(ia_valid & ATTR_ATIME_SET)) 117 attr->ia_atime = now; 118 if (!(ia_valid & ATTR_MTIME_SET)) 119 attr->ia_mtime = now; 120 if (ia_valid & ATTR_KILL_SUID) { 121 attr->ia_valid &= ~ATTR_KILL_SUID; 122 if (mode & S_ISUID) { 123 if (!(ia_valid & ATTR_MODE)) { 124 ia_valid = attr->ia_valid |= ATTR_MODE; 125 attr->ia_mode = inode->i_mode; 126 } 127 attr->ia_mode &= ~S_ISUID; 128 } 129 } 130 if (ia_valid & ATTR_KILL_SGID) { 131 attr->ia_valid &= ~ ATTR_KILL_SGID; 132 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 133 if (!(ia_valid & ATTR_MODE)) { 134 ia_valid = attr->ia_valid |= ATTR_MODE; 135 attr->ia_mode = inode->i_mode; 136 } 137 attr->ia_mode &= ~S_ISGID; 138 } 139 } 140 if (!attr->ia_valid) 141 return 0; 142 143 if (ia_valid & ATTR_SIZE) 144 down_write(&dentry->d_inode->i_alloc_sem); 145 146 if (inode->i_op && inode->i_op->setattr) { 147 error = security_inode_setattr(dentry, attr); 148 if (!error) 149 error = inode->i_op->setattr(dentry, attr); 150 } else { 151 error = inode_change_ok(inode, attr); 152 if (!error) 153 error = security_inode_setattr(dentry, attr); 154 if (!error) { 155 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 156 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) 157 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; 158 if (!error) 159 error = inode_setattr(inode, attr); 160 } 161 } 162 163 if (ia_valid & ATTR_SIZE) 164 up_write(&dentry->d_inode->i_alloc_sem); 165 166 if (!error) 167 fsnotify_change(dentry, ia_valid); 168 169 return error; 170 } 171 172 EXPORT_SYMBOL(notify_change); 173