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/sched.h> 9#include <linux/mm.h> 10#include <linux/string.h> 11#include <linux/smp_lock.h> 12#include <linux/dnotify.h> 13#include <linux/fcntl.h> 14#include <linux/quotaops.h> 15 16/* Taken over from the old code... */ 17 18/* POSIX UID/GID verification for setting inode attributes. */ 19int inode_change_ok(struct inode *inode, struct iattr *attr) 20{ 21 int retval = -EPERM; 22 unsigned int ia_valid = attr->ia_valid; 23 24 /* If force is set do it anyway. */ 25 if (ia_valid & ATTR_FORCE) 26 goto fine; 27 28 /* Make sure a caller can chown. */ 29 if ((ia_valid & ATTR_UID) && 30 (current->fsuid != inode->i_uid || 31 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN)) 32 goto error; 33 34 /* Make sure caller can chgrp. */ 35 if ((ia_valid & ATTR_GID) && 36 (current->fsuid != inode->i_uid || 37 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) && 38 !capable(CAP_CHOWN)) 39 goto error; 40 41 /* Make sure a caller can chmod. */ 42 if (ia_valid & ATTR_MODE) { 43 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 44 goto error; 45 /* Also check the setgid bit! */ 46 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : 47 inode->i_gid) && !capable(CAP_FSETID)) 48 attr->ia_mode &= ~S_ISGID; 49 } 50 51 /* Check for setting the inode time. */ 52 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) { 53 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) 54 goto error; 55 } 56fine: 57 retval = 0; 58error: 59 return retval; 60} 61 62int inode_setattr(struct inode * inode, struct iattr * attr) 63{ 64 unsigned int ia_valid = attr->ia_valid; 65 int error = 0; 66 67 if (ia_valid & ATTR_SIZE) { 68 error = vmtruncate(inode, attr->ia_size); 69 if (error) 70 goto out; 71 } 72 73 if (ia_valid & ATTR_UID) 74 inode->i_uid = attr->ia_uid; 75 if (ia_valid & ATTR_GID) 76 inode->i_gid = attr->ia_gid; 77 if (ia_valid & ATTR_ATIME) 78 inode->i_atime = attr->ia_atime; 79 if (ia_valid & ATTR_MTIME) 80 inode->i_mtime = attr->ia_mtime; 81 if (ia_valid & ATTR_CTIME) 82 inode->i_ctime = attr->ia_ctime; 83 if (ia_valid & ATTR_MODE) { 84 inode->i_mode = attr->ia_mode; 85 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 86 inode->i_mode &= ~S_ISGID; 87 } 88 mark_inode_dirty(inode); 89out: 90 return error; 91} 92 93static int setattr_mask(unsigned int ia_valid) 94{ 95 unsigned long dn_mask = 0; 96 97 if (ia_valid & ATTR_UID) 98 dn_mask |= DN_ATTRIB; 99 if (ia_valid & ATTR_GID) 100 dn_mask |= DN_ATTRIB; 101 if (ia_valid & ATTR_SIZE) 102 dn_mask |= DN_MODIFY; 103 /* both times implies a utime(s) call */ 104 if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME)) 105 dn_mask |= DN_ATTRIB; 106 else if (ia_valid & ATTR_ATIME) 107 dn_mask |= DN_ACCESS; 108 else if (ia_valid & ATTR_MTIME) 109 dn_mask |= DN_MODIFY; 110 if (ia_valid & ATTR_MODE) 111 dn_mask |= DN_ATTRIB; 112 return dn_mask; 113} 114 115int notify_change(struct dentry * dentry, struct iattr * attr) 116{ 117 struct inode *inode = dentry->d_inode; 118 int error; 119 time_t now = CURRENT_TIME; 120 unsigned int ia_valid = attr->ia_valid; 121 122 if (!inode) 123 BUG(); 124 125 attr->ia_ctime = now; 126 if (!(ia_valid & ATTR_ATIME_SET)) 127 attr->ia_atime = now; 128 if (!(ia_valid & ATTR_MTIME_SET)) 129 attr->ia_mtime = now; 130 131 lock_kernel(); 132 if (inode->i_op && inode->i_op->setattr) 133 error = inode->i_op->setattr(dentry, attr); 134 else { 135 error = inode_change_ok(inode, attr); 136 if (!error) { 137 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 138 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) 139 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; 140 if (!error) 141 error = inode_setattr(inode, attr); 142 } 143 } 144 unlock_kernel(); 145 if (!error) { 146 unsigned long dn_mask = setattr_mask(ia_valid); 147 if (dn_mask) 148 dnotify_parent(dentry, dn_mask); 149 } 150 return error; 151} 152

