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 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) && 37 !capable(CAP_CHOWN)) 38 goto error; 39 40 /* Make sure a caller can chmod. */ 41 if (ia_valid & ATTR_MODE) { 42 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 43 goto error; 44 /* Also check the setgid bit! */ 45 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : 46 inode->i_gid) && !capable(CAP_FSETID)) 47 attr->ia_mode &= ~S_ISGID; 48 } 49 50 /* Check for setting the inode time. */ 51 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) { 52 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) 53 goto error; 54 } 55fine: 56 retval = 0; 57error: 58 return retval; 59} 60 61int inode_setattr(struct inode * inode, struct iattr * attr) 62{ 63 unsigned int ia_valid = attr->ia_valid; 64 int error = 0; 65 66 if (ia_valid & ATTR_SIZE) { 67 error = vmtruncate(inode, attr->ia_size); 68 if (error) 69 goto out; 70 } 71 72 if (ia_valid & ATTR_UID) 73 inode->i_uid = attr->ia_uid; 74 if (ia_valid & ATTR_GID) 75 inode->i_gid = attr->ia_gid; 76 if (ia_valid & ATTR_ATIME) 77 inode->i_atime = attr->ia_atime; 78 if (ia_valid & ATTR_MTIME) 79 inode->i_mtime = attr->ia_mtime; 80 if (ia_valid & ATTR_CTIME) 81 inode->i_ctime = attr->ia_ctime; 82 if (ia_valid & ATTR_MODE) { 83 inode->i_mode = attr->ia_mode; 84 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 85 inode->i_mode &= ~S_ISGID; 86 } 87 mark_inode_dirty(inode); 88out: 89 return error; 90} 91 92static int setattr_mask(unsigned int ia_valid) 93{ 94 unsigned long dn_mask = 0; 95 96 if (ia_valid & ATTR_UID) 97 dn_mask |= DN_ATTRIB; 98 if (ia_valid & ATTR_GID) 99 dn_mask |= DN_ATTRIB; 100 if (ia_valid & ATTR_SIZE) 101 dn_mask |= DN_MODIFY; 102 /* both times implies a utime(s) call */ 103 if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME)) 104 dn_mask |= DN_ATTRIB; 105 else if (ia_valid & ATTR_ATIME) 106 dn_mask |= DN_ACCESS; 107 else if (ia_valid & ATTR_MTIME) 108 dn_mask |= DN_MODIFY; 109 if (ia_valid & ATTR_MODE) 110 dn_mask |= DN_ATTRIB; 111 return dn_mask; 112} 113 114int notify_change(struct dentry * dentry, struct iattr * attr) 115{ 116 struct inode *inode = dentry->d_inode; 117 int error; 118 time_t now = CURRENT_TIME; 119 unsigned int ia_valid = attr->ia_valid; 120 121 if (!inode) 122 BUG(); 123 124 attr->ia_ctime = now; 125 if (!(ia_valid & ATTR_ATIME_SET)) 126 attr->ia_atime = now; 127 if (!(ia_valid & ATTR_MTIME_SET)) 128 attr->ia_mtime = now; 129 130 lock_kernel(); 131 if (inode->i_op && inode->i_op->setattr) 132 error = inode->i_op->setattr(dentry, attr); 133 else { 134 error = inode_change_ok(inode, attr); 135 if (!error) { 136 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 137 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) 138 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; 139 if (!error) 140 error = inode_setattr(inode, attr); 141 } 142 } 143 unlock_kernel(); 144 if (!error) { 145 unsigned long dn_mask = setattr_mask(ia_valid); 146 if (dn_mask) 147 dnotify_parent(dentry, dn_mask); 148 } 149 return error; 150} 151

