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 12/* Taken over from the old code... */ 13 14/* POSIX UID/GID verification for setting inode attributes. */ 15int inode_change_ok(struct inode *inode, struct iattr *attr) 16{ 17 int retval = -EPERM; 18 unsigned int ia_valid = attr->ia_valid; 19 20 /* If force is set do it anyway. */ 21 if (ia_valid & ATTR_FORCE) 22 goto fine; 23 24 /* Make sure a caller can chown. */ 25 if ((ia_valid & ATTR_UID) && 26 (current->fsuid != inode->i_uid || 27 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN)) 28 goto error; 29 30 /* Make sure caller can chgrp. */ 31 if ((ia_valid & ATTR_GID) && 32 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) && 33 !capable(CAP_CHOWN)) 34 goto error; 35 36 /* Make sure a caller can chmod. */ 37 if (ia_valid & ATTR_MODE) { 38 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 39 goto error; 40 /* Also check the setgid bit! */ 41 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : 42 inode->i_gid) && !capable(CAP_FSETID)) 43 attr->ia_mode &= ~S_ISGID; 44 } 45 46 /* Check for setting the inode time. */ 47 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) { 48 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) 49 goto error; 50 } 51fine: 52 retval = 0; 53error: 54 return retval; 55} 56 57void inode_setattr(struct inode * inode, struct iattr * attr) 58{ 59 unsigned int ia_valid = attr->ia_valid; 60 61 if (ia_valid & ATTR_UID) 62 inode->i_uid = attr->ia_uid; 63 if (ia_valid & ATTR_GID) 64 inode->i_gid = attr->ia_gid; 65 if (ia_valid & ATTR_SIZE) 66 inode->i_size = attr->ia_size; 67 if (ia_valid & ATTR_ATIME) 68 inode->i_atime = attr->ia_atime; 69 if (ia_valid & ATTR_MTIME) 70 inode->i_mtime = attr->ia_mtime; 71 if (ia_valid & ATTR_CTIME) 72 inode->i_ctime = attr->ia_ctime; 73 if (ia_valid & ATTR_MODE) { 74 inode->i_mode = attr->ia_mode; 75 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 76 inode->i_mode &= ~S_ISGID; 77 } 78 mark_inode_dirty(inode); 79} 80 81int notify_change(struct dentry * dentry, struct iattr * attr) 82{ 83 struct inode *inode = dentry->d_inode; 84 int error; 85 time_t now = CURRENT_TIME; 86 unsigned int ia_valid = attr->ia_valid; 87 88 attr->ia_ctime = now; 89 if (!(ia_valid & ATTR_ATIME_SET)) 90 attr->ia_atime = now; 91 if (!(ia_valid & ATTR_MTIME_SET)) 92 attr->ia_mtime = now; 93 94 if (inode->i_sb && inode->i_sb->s_op && 95 inode->i_sb->s_op->notify_change) 96 error = inode->i_sb->s_op->notify_change(dentry, attr); 97 else { 98 error = inode_change_ok(inode, attr); 99 if (!error) 100 inode_setattr(inode, attr); 101 } 102 return error; 103} 104

