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