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 int error = 0; 71 72 if (ia_valid & ATTR_SIZE) { 73 if (attr->ia_size != i_size_read(inode)) { 74 error = vmtruncate(inode, attr->ia_size); 75 if (error || (ia_valid == ATTR_SIZE)) 76 goto out; 77 } else { 78 /* 79 * We skipped the truncate but must still update 80 * timestamps 81 */ 82 ia_valid |= ATTR_MTIME|ATTR_CTIME; 83 } 84 } 85 86 if (ia_valid & ATTR_UID) 87 inode->i_uid = attr->ia_uid; 88 if (ia_valid & ATTR_GID) 89 inode->i_gid = attr->ia_gid; 90 if (ia_valid & ATTR_ATIME) 91 inode->i_atime = timespec_trunc(attr->ia_atime, 92 inode->i_sb->s_time_gran); 93 if (ia_valid & ATTR_MTIME) 94 inode->i_mtime = timespec_trunc(attr->ia_mtime, 95 inode->i_sb->s_time_gran); 96 if (ia_valid & ATTR_CTIME) 97 inode->i_ctime = timespec_trunc(attr->ia_ctime, 98 inode->i_sb->s_time_gran); 99 if (ia_valid & ATTR_MODE) { 100 umode_t mode = attr->ia_mode; 101 102 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 103 mode &= ~S_ISGID; 104 inode->i_mode = mode; 105 } 106 mark_inode_dirty(inode); 107 out: 108 return error; 109 } 110 EXPORT_SYMBOL(inode_setattr); 111 112 int notify_change(struct dentry * dentry, struct iattr * attr) 113 { 114 struct inode *inode = dentry->d_inode; 115 mode_t mode; 116 int error; 117 struct timespec now; 118 unsigned int ia_valid = attr->ia_valid; 119 120 mode = inode->i_mode; 121 now = current_fs_time(inode->i_sb); 122 123 attr->ia_ctime = now; 124 if (!(ia_valid & ATTR_ATIME_SET)) 125 attr->ia_atime = now; 126 if (!(ia_valid & ATTR_MTIME_SET)) 127 attr->ia_mtime = now; 128 if (ia_valid & ATTR_KILL_SUID) { 129 attr->ia_valid &= ~ATTR_KILL_SUID; 130 if (mode & S_ISUID) { 131 if (!(ia_valid & ATTR_MODE)) { 132 ia_valid = attr->ia_valid |= ATTR_MODE; 133 attr->ia_mode = inode->i_mode; 134 } 135 attr->ia_mode &= ~S_ISUID; 136 } 137 } 138 if (ia_valid & ATTR_KILL_SGID) { 139 attr->ia_valid &= ~ ATTR_KILL_SGID; 140 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 141 if (!(ia_valid & ATTR_MODE)) { 142 ia_valid = attr->ia_valid |= ATTR_MODE; 143 attr->ia_mode = inode->i_mode; 144 } 145 attr->ia_mode &= ~S_ISGID; 146 } 147 } 148 if (!attr->ia_valid) 149 return 0; 150 151 if (ia_valid & ATTR_SIZE) 152 down_write(&dentry->d_inode->i_alloc_sem); 153 154 if (inode->i_op && inode->i_op->setattr) { 155 error = security_inode_setattr(dentry, attr); 156 if (!error) 157 error = inode->i_op->setattr(dentry, attr); 158 } else { 159 error = inode_change_ok(inode, attr); 160 if (!error) 161 error = security_inode_setattr(dentry, attr); 162 if (!error) { 163 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 164 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) 165 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; 166 if (!error) 167 error = inode_setattr(inode, attr); 168 } 169 } 170 171 if (ia_valid & ATTR_SIZE) 172 up_write(&dentry->d_inode->i_alloc_sem); 173 174 if (!error) 175 fsnotify_change(dentry, ia_valid); 176 177 return error; 178 } 179 180 EXPORT_SYMBOL(notify_change); 181