diff options
-rw-r--r-- | fs/cifs/cifsacl.c | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 38d09fa8c1e6..ec445802d903 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -134,12 +134,39 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
134 | pmode is the existing mode (we only want to overwrite part of this | 134 | pmode is the existing mode (we only want to overwrite part of this |
135 | bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 | 135 | bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 |
136 | */ | 136 | */ |
137 | static void access_flags_to_mode(__u32 ace_flags, umode_t *pmode, | 137 | static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode, |
138 | umode_t bits_to_set) | 138 | umode_t *pbits_to_set) |
139 | { | 139 | { |
140 | /* the order of ACEs is important. The canonical order is to begin with | ||
141 | DENY entries then follow with ALLOW, otherwise an allow entry could be | ||
142 | encountered first, making the subsequent deny entry like "dead code" | ||
143 | which would be superflous since Windows stops when a match is made | ||
144 | for the operation you are trying to perform for your user */ | ||
145 | |||
146 | /* For deny ACEs we change the mask so that subsequent allow access | ||
147 | control entries do not turn on the bits we are denying */ | ||
148 | if (type == ACCESS_DENIED) { | ||
149 | if (ace_flags & GENERIC_ALL) { | ||
150 | *pbits_to_set &= ~S_IRWXUGO; | ||
151 | } | ||
152 | if ((ace_flags & GENERIC_WRITE) || | ||
153 | ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) | ||
154 | *pbits_to_set &= ~S_IWUGO; | ||
155 | if ((ace_flags & GENERIC_READ) || | ||
156 | ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) | ||
157 | *pbits_to_set &= ~S_IRUGO; | ||
158 | if ((ace_flags & GENERIC_EXECUTE) || | ||
159 | ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) | ||
160 | *pbits_to_set &= ~S_IXUGO; | ||
161 | return; | ||
162 | } else if (type != ACCESS_ALLOWED) { | ||
163 | cERROR(1, ("unknown access control type %d", type)); | ||
164 | return; | ||
165 | } | ||
166 | /* else ACCESS_ALLOWED type */ | ||
140 | 167 | ||
141 | if (ace_flags & GENERIC_ALL) { | 168 | if (ace_flags & GENERIC_ALL) { |
142 | *pmode |= (S_IRWXUGO & bits_to_set); | 169 | *pmode |= (S_IRWXUGO & (*pbits_to_set)); |
143 | #ifdef CONFIG_CIFS_DEBUG2 | 170 | #ifdef CONFIG_CIFS_DEBUG2 |
144 | cFYI(1, ("all perms")); | 171 | cFYI(1, ("all perms")); |
145 | #endif | 172 | #endif |
@@ -147,13 +174,13 @@ static void access_flags_to_mode(__u32 ace_flags, umode_t *pmode, | |||
147 | } | 174 | } |
148 | if ((ace_flags & GENERIC_WRITE) || | 175 | if ((ace_flags & GENERIC_WRITE) || |
149 | ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) | 176 | ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) |
150 | *pmode |= (S_IWUGO & bits_to_set); | 177 | *pmode |= (S_IWUGO & (*pbits_to_set)); |
151 | if ((ace_flags & GENERIC_READ) || | 178 | if ((ace_flags & GENERIC_READ) || |
152 | ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) | 179 | ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) |
153 | *pmode |= (S_IRUGO & bits_to_set); | 180 | *pmode |= (S_IRUGO & (*pbits_to_set)); |
154 | if ((ace_flags & GENERIC_EXECUTE) || | 181 | if ((ace_flags & GENERIC_EXECUTE) || |
155 | ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) | 182 | ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) |
156 | *pmode |= (S_IXUGO & bits_to_set); | 183 | *pmode |= (S_IXUGO & (*pbits_to_set)); |
157 | 184 | ||
158 | #ifdef CONFIG_CIFS_DEBUG2 | 185 | #ifdef CONFIG_CIFS_DEBUG2 |
159 | cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode)); | 186 | cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode)); |
@@ -239,6 +266,10 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
239 | 266 | ||
240 | num_aces = le32_to_cpu(pdacl->num_aces); | 267 | num_aces = le32_to_cpu(pdacl->num_aces); |
241 | if (num_aces > 0) { | 268 | if (num_aces > 0) { |
269 | umode_t user_mask = S_IRWXU; | ||
270 | umode_t group_mask = S_IRWXG; | ||
271 | umode_t other_mask = S_IRWXO; | ||
272 | |||
242 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | 273 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), |
243 | GFP_KERNEL); | 274 | GFP_KERNEL); |
244 | 275 | ||
@@ -253,13 +284,19 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
253 | #endif | 284 | #endif |
254 | if (compare_sids(&(ppace[i]->sid), pownersid)) | 285 | if (compare_sids(&(ppace[i]->sid), pownersid)) |
255 | access_flags_to_mode(ppace[i]->access_req, | 286 | access_flags_to_mode(ppace[i]->access_req, |
256 | &(inode->i_mode), S_IRWXU); | 287 | ppace[i]->type, |
288 | &(inode->i_mode), | ||
289 | &user_mask); | ||
257 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | 290 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) |
258 | access_flags_to_mode(ppace[i]->access_req, | 291 | access_flags_to_mode(ppace[i]->access_req, |
259 | &(inode->i_mode), S_IRWXG); | 292 | ppace[i]->type, |
293 | &(inode->i_mode), | ||
294 | &group_mask); | ||
260 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | 295 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) |
261 | access_flags_to_mode(ppace[i]->access_req, | 296 | access_flags_to_mode(ppace[i]->access_req, |
262 | &(inode->i_mode), S_IRWXO); | 297 | ppace[i]->type, |
298 | &(inode->i_mode), | ||
299 | &other_mask); | ||
263 | 300 | ||
264 | /* memcpy((void *)(&(cifscred->aces[i])), | 301 | /* memcpy((void *)(&(cifscred->aces[i])), |
265 | (void *)ppace[i], | 302 | (void *)ppace[i], |