1
2
3
4
5
6
7
8#include <linux/time.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#include <linux/security.h>
16
17
18
19
20int inode_change_ok(struct inode *inode, struct iattr *attr)
21{
22 int retval = -EPERM;
23 unsigned int ia_valid = attr->ia_valid;
24
25 lock_kernel();
26
27
28 if (ia_valid & ATTR_FORCE)
29 goto fine;
30
31
32 if ((ia_valid & ATTR_UID) &&
33 (current->fsuid != inode->i_uid ||
34 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
35 goto error;
36
37
38 if ((ia_valid & ATTR_GID) &&
39 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
40 !capable(CAP_CHOWN))
41 goto error;
42
43
44 if (ia_valid & ATTR_MODE) {
45 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
46 goto error;
47
48 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
49 inode->i_gid) && !capable(CAP_FSETID))
50 attr->ia_mode &= ~S_ISGID;
51 }
52
53
54 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
55 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
56 goto error;
57 }
58fine:
59 retval = 0;
60error:
61 unlock_kernel();
62 return retval;
63}
64
65int inode_setattr(struct inode * inode, struct iattr * attr)
66{
67 unsigned int ia_valid = attr->ia_valid;
68 int error = 0;
69
70 lock_kernel();
71 if (ia_valid & ATTR_SIZE) {
72 error = vmtruncate(inode, attr->ia_size);
73 if (error)
74 goto out;
75 }
76
77 if (ia_valid & ATTR_UID)
78 inode->i_uid = attr->ia_uid;
79 if (ia_valid & ATTR_GID)
80 inode->i_gid = attr->ia_gid;
81 if (ia_valid & ATTR_ATIME)
82 inode->i_atime = attr->ia_atime;
83 if (ia_valid & ATTR_MTIME)
84 inode->i_mtime = attr->ia_mtime;
85 if (ia_valid & ATTR_CTIME)
86 inode->i_ctime = attr->ia_ctime;
87 if (ia_valid & ATTR_MODE) {
88 inode->i_mode = attr->ia_mode;
89 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
90 inode->i_mode &= ~S_ISGID;
91 }
92 mark_inode_dirty(inode);
93out:
94 unlock_kernel();
95 return error;
96}
97
98static int setattr_mask(unsigned int ia_valid)
99{
100 unsigned long dn_mask = 0;
101
102 if (ia_valid & ATTR_UID)
103 dn_mask |= DN_ATTRIB;
104 if (ia_valid & ATTR_GID)
105 dn_mask |= DN_ATTRIB;
106 if (ia_valid & ATTR_SIZE)
107 dn_mask |= DN_MODIFY;
108
109 if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
110 dn_mask |= DN_ATTRIB;
111 else if (ia_valid & ATTR_ATIME)
112 dn_mask |= DN_ACCESS;
113 else if (ia_valid & ATTR_MTIME)
114 dn_mask |= DN_MODIFY;
115 if (ia_valid & ATTR_MODE)
116 dn_mask |= DN_ATTRIB;
117 return dn_mask;
118}
119
120int notify_change(struct dentry * dentry, struct iattr * attr)
121{
122 struct inode *inode = dentry->d_inode;
123 mode_t mode = inode->i_mode;
124 int error;
125 time_t now = CURRENT_TIME;
126 unsigned int ia_valid = attr->ia_valid;
127
128 if (!inode)
129 BUG();
130
131 attr->ia_ctime = now;
132 if (!(ia_valid & ATTR_ATIME_SET))
133 attr->ia_atime = now;
134 if (!(ia_valid & ATTR_MTIME_SET))
135 attr->ia_mtime = now;
136 if (ia_valid & ATTR_KILL_SUID) {
137 if (mode & S_ISUID) {
138 if (!(ia_valid & ATTR_MODE)) {
139 ia_valid = attr->ia_valid |= ATTR_MODE;
140 attr->ia_mode = inode->i_mode;
141 }
142 attr->ia_mode &= ~S_ISUID;
143 }
144 }
145 if (ia_valid & ATTR_KILL_SGID) {
146 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
147 if (!(ia_valid & ATTR_MODE)) {
148 ia_valid = attr->ia_valid |= ATTR_MODE;
149 attr->ia_mode = inode->i_mode;
150 }
151 attr->ia_mode &= ~S_ISGID;
152 }
153 }
154
155 if (inode->i_op && inode->i_op->setattr) {
156 error = security_ops->inode_setattr(dentry, attr);
157 if (!error)
158 error = inode->i_op->setattr(dentry, attr);
159 } else {
160 error = inode_change_ok(inode, attr);
161 if (!error)
162 error = security_ops->inode_setattr(dentry, attr);
163 if (!error) {
164 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
165 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
166 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
167 if (!error)
168 error = inode_setattr(inode, attr);
169 }
170 }
171 if (!error) {
172 unsigned long dn_mask = setattr_mask(ia_valid);
173 if (dn_mask)
174 dnotify_parent(dentry, dn_mask);
175 }
176 return error;
177}
178