xref: /openbmc/linux/fs/attr.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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