aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsacl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r--fs/cifs/cifsacl.c135
1 files changed, 83 insertions, 52 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 992f1fb299d1..72ddf23ef6f7 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -904,7 +904,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
904 acl_size = sizeof(struct cifs_acl); 904 acl_size = sizeof(struct cifs_acl);
905 905
906 num_aces = le32_to_cpu(pdacl->num_aces); 906 num_aces = le32_to_cpu(pdacl->num_aces);
907 if (num_aces > 0) { 907 if (num_aces > 0) {
908 umode_t user_mask = S_IRWXU; 908 umode_t user_mask = S_IRWXU;
909 umode_t group_mask = S_IRWXG; 909 umode_t group_mask = S_IRWXG;
910 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO; 910 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
@@ -1066,52 +1066,82 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
1066 else 1066 else
1067 cFYI(1, "no ACL"); /* BB grant all or default perms? */ 1067 cFYI(1, "no ACL"); /* BB grant all or default perms? */
1068 1068
1069/* cifscred->uid = owner_sid_ptr->rid;
1070 cifscred->gid = group_sid_ptr->rid;
1071 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
1072 sizeof(struct cifs_sid));
1073 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
1074 sizeof(struct cifs_sid)); */
1075
1076 return rc; 1069 return rc;
1077} 1070}
1078 1071
1079
1080/* Convert permission bits from mode to equivalent CIFS ACL */ 1072/* Convert permission bits from mode to equivalent CIFS ACL */
1081static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, 1073static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
1082 struct inode *inode, __u64 nmode) 1074 __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
1083{ 1075{
1084 int rc = 0; 1076 int rc = 0;
1085 __u32 dacloffset; 1077 __u32 dacloffset;
1086 __u32 ndacloffset; 1078 __u32 ndacloffset;
1087 __u32 sidsoffset; 1079 __u32 sidsoffset;
1088 struct cifs_sid *owner_sid_ptr, *group_sid_ptr; 1080 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1081 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
1089 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */ 1082 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1090 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ 1083 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
1091 1084
1092 if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL)) 1085 if (nmode != NO_CHANGE_64) { /* chmod */
1093 return -EIO; 1086 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1094
1095 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1096 le32_to_cpu(pntsd->osidoffset)); 1087 le32_to_cpu(pntsd->osidoffset));
1097 group_sid_ptr = (struct cifs_sid *)((char *)pntsd + 1088 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1098 le32_to_cpu(pntsd->gsidoffset)); 1089 le32_to_cpu(pntsd->gsidoffset));
1099 1090 dacloffset = le32_to_cpu(pntsd->dacloffset);
1100 dacloffset = le32_to_cpu(pntsd->dacloffset); 1091 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1101 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); 1092 ndacloffset = sizeof(struct cifs_ntsd);
1102 1093 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1103 ndacloffset = sizeof(struct cifs_ntsd); 1094 ndacl_ptr->revision = dacl_ptr->revision;
1104 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); 1095 ndacl_ptr->size = 0;
1105 ndacl_ptr->revision = dacl_ptr->revision; 1096 ndacl_ptr->num_aces = 0;
1106 ndacl_ptr->size = 0; 1097
1107 ndacl_ptr->num_aces = 0; 1098 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
1108 1099 nmode);
1109 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode); 1100 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1110 1101 /* copy sec desc control portion & owner and group sids */
1111 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); 1102 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1112 1103 *aclflag = CIFS_ACL_DACL;
1113 /* copy security descriptor control portion and owner and group sid */ 1104 } else {
1114 copy_sec_desc(pntsd, pnntsd, sidsoffset); 1105 memcpy(pnntsd, pntsd, secdesclen);
1106 if (uid != NO_CHANGE_32) { /* chown */
1107 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1108 le32_to_cpu(pnntsd->osidoffset));
1109 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1110 GFP_KERNEL);
1111 if (!nowner_sid_ptr)
1112 return -ENOMEM;
1113 rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
1114 if (rc) {
1115 cFYI(1, "%s: Mapping error %d for owner id %d",
1116 __func__, rc, uid);
1117 kfree(nowner_sid_ptr);
1118 return rc;
1119 }
1120 memcpy(owner_sid_ptr, nowner_sid_ptr,
1121 sizeof(struct cifs_sid));
1122 kfree(nowner_sid_ptr);
1123 *aclflag = CIFS_ACL_OWNER;
1124 }
1125 if (gid != NO_CHANGE_32) { /* chgrp */
1126 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1127 le32_to_cpu(pnntsd->gsidoffset));
1128 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1129 GFP_KERNEL);
1130 if (!ngroup_sid_ptr)
1131 return -ENOMEM;
1132 rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
1133 if (rc) {
1134 cFYI(1, "%s: Mapping error %d for group id %d",
1135 __func__, rc, gid);
1136 kfree(ngroup_sid_ptr);
1137 return rc;
1138 }
1139 memcpy(group_sid_ptr, ngroup_sid_ptr,
1140 sizeof(struct cifs_sid));
1141 kfree(ngroup_sid_ptr);
1142 *aclflag = CIFS_ACL_GROUP;
1143 }
1144 }
1115 1145
1116 return rc; 1146 return rc;
1117} 1147}
@@ -1192,13 +1222,15 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1192 return pntsd; 1222 return pntsd;
1193} 1223}
1194 1224
1195static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, 1225 /* Set an ACL on the server */
1196 struct cifs_ntsd *pnntsd, u32 acllen) 1226int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1227 struct inode *inode, const char *path, int aclflag)
1197{ 1228{
1198 int oplock = 0; 1229 int oplock = 0;
1199 int xid, rc, create_options = 0; 1230 int xid, rc, access_flags, create_options = 0;
1200 __u16 fid; 1231 __u16 fid;
1201 struct cifs_tcon *tcon; 1232 struct cifs_tcon *tcon;
1233 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1202 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); 1234 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1203 1235
1204 if (IS_ERR(tlink)) 1236 if (IS_ERR(tlink))
@@ -1210,15 +1242,20 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
1210 if (backup_cred(cifs_sb)) 1242 if (backup_cred(cifs_sb))
1211 create_options |= CREATE_OPEN_BACKUP_INTENT; 1243 create_options |= CREATE_OPEN_BACKUP_INTENT;
1212 1244
1213 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, create_options, 1245 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1214 &fid, &oplock, NULL, cifs_sb->local_nls, 1246 access_flags = WRITE_OWNER;
1215 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 1247 else
1248 access_flags = WRITE_DAC;
1249
1250 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
1251 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1252 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1216 if (rc) { 1253 if (rc) {
1217 cERROR(1, "Unable to open file to set ACL"); 1254 cERROR(1, "Unable to open file to set ACL");
1218 goto out; 1255 goto out;
1219 } 1256 }
1220 1257
1221 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen); 1258 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
1222 cFYI(DBG2, "SetCIFSACL rc = %d", rc); 1259 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1223 1260
1224 CIFSSMBClose(xid, tcon, fid); 1261 CIFSSMBClose(xid, tcon, fid);
@@ -1228,17 +1265,6 @@ out:
1228 return rc; 1265 return rc;
1229} 1266}
1230 1267
1231/* Set an ACL on the server */
1232int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1233 struct inode *inode, const char *path)
1234{
1235 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1236
1237 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
1238
1239 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
1240}
1241
1242/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 1268/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1243int 1269int
1244cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, 1270cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
@@ -1270,9 +1296,12 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1270} 1296}
1271 1297
1272/* Convert mode bits to an ACL so we can update the ACL on the server */ 1298/* Convert mode bits to an ACL so we can update the ACL on the server */
1273int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode) 1299int
1300id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1301 uid_t uid, gid_t gid)
1274{ 1302{
1275 int rc = 0; 1303 int rc = 0;
1304 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1276 __u32 secdesclen = 0; 1305 __u32 secdesclen = 0;
1277 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ 1306 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1278 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ 1307 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
@@ -1302,13 +1331,15 @@ int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
1302 return -ENOMEM; 1331 return -ENOMEM;
1303 } 1332 }
1304 1333
1305 rc = build_sec_desc(pntsd, pnntsd, inode, nmode); 1334 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1335 &aclflag);
1306 1336
1307 cFYI(DBG2, "build_sec_desc rc: %d", rc); 1337 cFYI(DBG2, "build_sec_desc rc: %d", rc);
1308 1338
1309 if (!rc) { 1339 if (!rc) {
1310 /* Set the security descriptor */ 1340 /* Set the security descriptor */
1311 rc = set_cifs_acl(pnntsd, secdesclen, inode, path); 1341 rc = set_cifs_acl(pnntsd, secdesclen, inode,
1342 path, aclflag);
1312 cFYI(DBG2, "set_cifs_acl rc: %d", rc); 1343 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1313 } 1344 }
1314 1345