0001
0002
0003
0004
0005
0006
0007 #include <linux/fs.h>
0008
0009 #include "glob.h"
0010 #include "ndr.h"
0011
0012 static inline char *ndr_get_field(struct ndr *n)
0013 {
0014 return n->data + n->offset;
0015 }
0016
0017 static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
0018 {
0019 char *data;
0020
0021 data = krealloc(n->data, n->offset + sz + 1024, GFP_KERNEL);
0022 if (!data)
0023 return -ENOMEM;
0024
0025 n->data = data;
0026 n->length += 1024;
0027 memset(n->data + n->offset, 0, 1024);
0028 return 0;
0029 }
0030
0031 static int ndr_write_int16(struct ndr *n, __u16 value)
0032 {
0033 if (n->length <= n->offset + sizeof(value)) {
0034 int ret;
0035
0036 ret = try_to_realloc_ndr_blob(n, sizeof(value));
0037 if (ret)
0038 return ret;
0039 }
0040
0041 *(__le16 *)ndr_get_field(n) = cpu_to_le16(value);
0042 n->offset += sizeof(value);
0043 return 0;
0044 }
0045
0046 static int ndr_write_int32(struct ndr *n, __u32 value)
0047 {
0048 if (n->length <= n->offset + sizeof(value)) {
0049 int ret;
0050
0051 ret = try_to_realloc_ndr_blob(n, sizeof(value));
0052 if (ret)
0053 return ret;
0054 }
0055
0056 *(__le32 *)ndr_get_field(n) = cpu_to_le32(value);
0057 n->offset += sizeof(value);
0058 return 0;
0059 }
0060
0061 static int ndr_write_int64(struct ndr *n, __u64 value)
0062 {
0063 if (n->length <= n->offset + sizeof(value)) {
0064 int ret;
0065
0066 ret = try_to_realloc_ndr_blob(n, sizeof(value));
0067 if (ret)
0068 return ret;
0069 }
0070
0071 *(__le64 *)ndr_get_field(n) = cpu_to_le64(value);
0072 n->offset += sizeof(value);
0073 return 0;
0074 }
0075
0076 static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
0077 {
0078 if (n->length <= n->offset + sz) {
0079 int ret;
0080
0081 ret = try_to_realloc_ndr_blob(n, sz);
0082 if (ret)
0083 return ret;
0084 }
0085
0086 memcpy(ndr_get_field(n), value, sz);
0087 n->offset += sz;
0088 return 0;
0089 }
0090
0091 static int ndr_write_string(struct ndr *n, char *value)
0092 {
0093 size_t sz;
0094
0095 sz = strlen(value) + 1;
0096 if (n->length <= n->offset + sz) {
0097 int ret;
0098
0099 ret = try_to_realloc_ndr_blob(n, sz);
0100 if (ret)
0101 return ret;
0102 }
0103
0104 memcpy(ndr_get_field(n), value, sz);
0105 n->offset += sz;
0106 n->offset = ALIGN(n->offset, 2);
0107 return 0;
0108 }
0109
0110 static int ndr_read_string(struct ndr *n, void *value, size_t sz)
0111 {
0112 int len;
0113
0114 if (n->offset + sz > n->length)
0115 return -EINVAL;
0116
0117 len = strnlen(ndr_get_field(n), sz);
0118 if (value)
0119 memcpy(value, ndr_get_field(n), len);
0120 len++;
0121 n->offset += len;
0122 n->offset = ALIGN(n->offset, 2);
0123 return 0;
0124 }
0125
0126 static int ndr_read_bytes(struct ndr *n, void *value, size_t sz)
0127 {
0128 if (n->offset + sz > n->length)
0129 return -EINVAL;
0130
0131 if (value)
0132 memcpy(value, ndr_get_field(n), sz);
0133 n->offset += sz;
0134 return 0;
0135 }
0136
0137 static int ndr_read_int16(struct ndr *n, __u16 *value)
0138 {
0139 if (n->offset + sizeof(__u16) > n->length)
0140 return -EINVAL;
0141
0142 if (value)
0143 *value = le16_to_cpu(*(__le16 *)ndr_get_field(n));
0144 n->offset += sizeof(__u16);
0145 return 0;
0146 }
0147
0148 static int ndr_read_int32(struct ndr *n, __u32 *value)
0149 {
0150 if (n->offset + sizeof(__u32) > n->length)
0151 return -EINVAL;
0152
0153 if (value)
0154 *value = le32_to_cpu(*(__le32 *)ndr_get_field(n));
0155 n->offset += sizeof(__u32);
0156 return 0;
0157 }
0158
0159 static int ndr_read_int64(struct ndr *n, __u64 *value)
0160 {
0161 if (n->offset + sizeof(__u64) > n->length)
0162 return -EINVAL;
0163
0164 if (value)
0165 *value = le64_to_cpu(*(__le64 *)ndr_get_field(n));
0166 n->offset += sizeof(__u64);
0167 return 0;
0168 }
0169
0170 int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
0171 {
0172 char hex_attr[12] = {0};
0173 int ret;
0174
0175 n->offset = 0;
0176 n->length = 1024;
0177 n->data = kzalloc(n->length, GFP_KERNEL);
0178 if (!n->data)
0179 return -ENOMEM;
0180
0181 if (da->version == 3) {
0182 snprintf(hex_attr, 10, "0x%x", da->attr);
0183 ret = ndr_write_string(n, hex_attr);
0184 } else {
0185 ret = ndr_write_string(n, "");
0186 }
0187 if (ret)
0188 return ret;
0189
0190 ret = ndr_write_int16(n, da->version);
0191 if (ret)
0192 return ret;
0193
0194 ret = ndr_write_int32(n, da->version);
0195 if (ret)
0196 return ret;
0197
0198 ret = ndr_write_int32(n, da->flags);
0199 if (ret)
0200 return ret;
0201
0202 ret = ndr_write_int32(n, da->attr);
0203 if (ret)
0204 return ret;
0205
0206 if (da->version == 3) {
0207 ret = ndr_write_int32(n, da->ea_size);
0208 if (ret)
0209 return ret;
0210 ret = ndr_write_int64(n, da->size);
0211 if (ret)
0212 return ret;
0213 ret = ndr_write_int64(n, da->alloc_size);
0214 } else {
0215 ret = ndr_write_int64(n, da->itime);
0216 }
0217 if (ret)
0218 return ret;
0219
0220 ret = ndr_write_int64(n, da->create_time);
0221 if (ret)
0222 return ret;
0223
0224 if (da->version == 3)
0225 ret = ndr_write_int64(n, da->change_time);
0226 return ret;
0227 }
0228
0229 int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
0230 {
0231 char hex_attr[12];
0232 unsigned int version2;
0233 int ret;
0234
0235 n->offset = 0;
0236 ret = ndr_read_string(n, hex_attr, sizeof(hex_attr));
0237 if (ret)
0238 return ret;
0239
0240 ret = ndr_read_int16(n, &da->version);
0241 if (ret)
0242 return ret;
0243
0244 if (da->version != 3 && da->version != 4) {
0245 pr_err("v%d version is not supported\n", da->version);
0246 return -EINVAL;
0247 }
0248
0249 ret = ndr_read_int32(n, &version2);
0250 if (ret)
0251 return ret;
0252
0253 if (da->version != version2) {
0254 pr_err("ndr version mismatched(version: %d, version2: %d)\n",
0255 da->version, version2);
0256 return -EINVAL;
0257 }
0258
0259 ret = ndr_read_int32(n, NULL);
0260 if (ret)
0261 return ret;
0262
0263 ret = ndr_read_int32(n, &da->attr);
0264 if (ret)
0265 return ret;
0266
0267 if (da->version == 4) {
0268 ret = ndr_read_int64(n, &da->itime);
0269 if (ret)
0270 return ret;
0271
0272 ret = ndr_read_int64(n, &da->create_time);
0273 } else {
0274 ret = ndr_read_int32(n, NULL);
0275 if (ret)
0276 return ret;
0277
0278 ret = ndr_read_int64(n, NULL);
0279 if (ret)
0280 return ret;
0281
0282 ret = ndr_read_int64(n, NULL);
0283 if (ret)
0284 return ret;
0285
0286 ret = ndr_read_int64(n, &da->create_time);
0287 if (ret)
0288 return ret;
0289
0290 ret = ndr_read_int64(n, NULL);
0291 }
0292
0293 return ret;
0294 }
0295
0296 static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
0297 {
0298 int i, ret;
0299
0300 ret = ndr_write_int32(n, acl->count);
0301 if (ret)
0302 return ret;
0303
0304 n->offset = ALIGN(n->offset, 8);
0305 ret = ndr_write_int32(n, acl->count);
0306 if (ret)
0307 return ret;
0308
0309 ret = ndr_write_int32(n, 0);
0310 if (ret)
0311 return ret;
0312
0313 for (i = 0; i < acl->count; i++) {
0314 n->offset = ALIGN(n->offset, 8);
0315 ret = ndr_write_int16(n, acl->entries[i].type);
0316 if (ret)
0317 return ret;
0318
0319 ret = ndr_write_int16(n, acl->entries[i].type);
0320 if (ret)
0321 return ret;
0322
0323 if (acl->entries[i].type == SMB_ACL_USER) {
0324 n->offset = ALIGN(n->offset, 8);
0325 ret = ndr_write_int64(n, acl->entries[i].uid);
0326 } else if (acl->entries[i].type == SMB_ACL_GROUP) {
0327 n->offset = ALIGN(n->offset, 8);
0328 ret = ndr_write_int64(n, acl->entries[i].gid);
0329 }
0330 if (ret)
0331 return ret;
0332
0333
0334 ret = ndr_write_int32(n, acl->entries[i].perm);
0335 }
0336
0337 return ret;
0338 }
0339
0340 int ndr_encode_posix_acl(struct ndr *n,
0341 struct user_namespace *user_ns,
0342 struct inode *inode,
0343 struct xattr_smb_acl *acl,
0344 struct xattr_smb_acl *def_acl)
0345 {
0346 unsigned int ref_id = 0x00020000;
0347 int ret;
0348
0349 n->offset = 0;
0350 n->length = 1024;
0351 n->data = kzalloc(n->length, GFP_KERNEL);
0352 if (!n->data)
0353 return -ENOMEM;
0354
0355 if (acl) {
0356
0357 ret = ndr_write_int32(n, ref_id);
0358 ref_id += 4;
0359 } else {
0360 ret = ndr_write_int32(n, 0);
0361 }
0362 if (ret)
0363 return ret;
0364
0365 if (def_acl) {
0366
0367 ret = ndr_write_int32(n, ref_id);
0368 ref_id += 4;
0369 } else {
0370 ret = ndr_write_int32(n, 0);
0371 }
0372 if (ret)
0373 return ret;
0374
0375 ret = ndr_write_int64(n, from_kuid(&init_user_ns, i_uid_into_mnt(user_ns, inode)));
0376 if (ret)
0377 return ret;
0378 ret = ndr_write_int64(n, from_kgid(&init_user_ns, i_gid_into_mnt(user_ns, inode)));
0379 if (ret)
0380 return ret;
0381 ret = ndr_write_int32(n, inode->i_mode);
0382 if (ret)
0383 return ret;
0384
0385 if (acl) {
0386 ret = ndr_encode_posix_acl_entry(n, acl);
0387 if (def_acl && !ret)
0388 ret = ndr_encode_posix_acl_entry(n, def_acl);
0389 }
0390 return ret;
0391 }
0392
0393 int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
0394 {
0395 unsigned int ref_id = 0x00020004;
0396 int ret;
0397
0398 n->offset = 0;
0399 n->length = 2048;
0400 n->data = kzalloc(n->length, GFP_KERNEL);
0401 if (!n->data)
0402 return -ENOMEM;
0403
0404 ret = ndr_write_int16(n, acl->version);
0405 if (ret)
0406 return ret;
0407
0408 ret = ndr_write_int32(n, acl->version);
0409 if (ret)
0410 return ret;
0411
0412 ret = ndr_write_int16(n, 2);
0413 if (ret)
0414 return ret;
0415
0416 ret = ndr_write_int32(n, ref_id);
0417 if (ret)
0418 return ret;
0419
0420
0421 ret = ndr_write_int16(n, acl->hash_type);
0422 if (ret)
0423 return ret;
0424
0425 ret = ndr_write_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
0426 if (ret)
0427 return ret;
0428
0429 ret = ndr_write_bytes(n, acl->desc, acl->desc_len);
0430 if (ret)
0431 return ret;
0432
0433 ret = ndr_write_int64(n, acl->current_time);
0434 if (ret)
0435 return ret;
0436
0437 ret = ndr_write_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
0438 if (ret)
0439 return ret;
0440
0441
0442 ret = ndr_write_bytes(n, acl->sd_buf, acl->sd_size);
0443 return ret;
0444 }
0445
0446 int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
0447 {
0448 unsigned int version2;
0449 int ret;
0450
0451 n->offset = 0;
0452 ret = ndr_read_int16(n, &acl->version);
0453 if (ret)
0454 return ret;
0455 if (acl->version != 4) {
0456 pr_err("v%d version is not supported\n", acl->version);
0457 return -EINVAL;
0458 }
0459
0460 ret = ndr_read_int32(n, &version2);
0461 if (ret)
0462 return ret;
0463 if (acl->version != version2) {
0464 pr_err("ndr version mismatched(version: %d, version2: %d)\n",
0465 acl->version, version2);
0466 return -EINVAL;
0467 }
0468
0469
0470 ret = ndr_read_int16(n, NULL);
0471 if (ret)
0472 return ret;
0473
0474
0475 ret = ndr_read_int32(n, NULL);
0476 if (ret)
0477 return ret;
0478
0479 ret = ndr_read_int16(n, &acl->hash_type);
0480 if (ret)
0481 return ret;
0482
0483 ret = ndr_read_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
0484 if (ret)
0485 return ret;
0486
0487 ndr_read_bytes(n, acl->desc, 10);
0488 if (strncmp(acl->desc, "posix_acl", 9)) {
0489 pr_err("Invalid acl description : %s\n", acl->desc);
0490 return -EINVAL;
0491 }
0492
0493
0494 ret = ndr_read_int64(n, NULL);
0495 if (ret)
0496 return ret;
0497
0498
0499 ret = ndr_read_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
0500 if (ret)
0501 return ret;
0502
0503 acl->sd_size = n->length - n->offset;
0504 acl->sd_buf = kzalloc(acl->sd_size, GFP_KERNEL);
0505 if (!acl->sd_buf)
0506 return -ENOMEM;
0507
0508 ret = ndr_read_bytes(n, acl->sd_buf, acl->sd_size);
0509 return ret;
0510 }