1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2024 Paulo Alcantara <pc@manguebit.com> 4 */ 5 6 #include <linux/fs.h> 7 #include <linux/stat.h> 8 #include <linux/slab.h> 9 #include "cifsglob.h" 10 #include "smb2proto.h" 11 #include "cifsproto.h" 12 #include "cifs_unicode.h" 13 #include "cifs_debug.h" 14 #include "fs_context.h" 15 #include "reparse.h" 16 17 int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode, 18 struct dentry *dentry, struct cifs_tcon *tcon, 19 const char *full_path, const char *symname) 20 { 21 struct reparse_symlink_data_buffer *buf = NULL; 22 struct cifs_open_info_data data; 23 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 24 struct inode *new; 25 struct kvec iov; 26 __le16 *path; 27 char *sym, sep = CIFS_DIR_SEP(cifs_sb); 28 u16 len, plen; 29 int rc = 0; 30 31 sym = kstrdup(symname, GFP_KERNEL); 32 if (!sym) 33 return -ENOMEM; 34 35 data = (struct cifs_open_info_data) { 36 .reparse_point = true, 37 .reparse = { .tag = IO_REPARSE_TAG_SYMLINK, }, 38 .symlink_target = sym, 39 }; 40 41 convert_delimiter(sym, sep); 42 path = cifs_convert_path_to_utf16(sym, cifs_sb); 43 if (!path) { 44 rc = -ENOMEM; 45 goto out; 46 } 47 48 plen = 2 * UniStrnlen((wchar_t *)path, PATH_MAX); 49 len = sizeof(*buf) + plen * 2; 50 buf = kzalloc(len, GFP_KERNEL); 51 if (!buf) { 52 rc = -ENOMEM; 53 goto out; 54 } 55 56 buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_SYMLINK); 57 buf->ReparseDataLength = cpu_to_le16(len - sizeof(struct reparse_data_buffer)); 58 buf->SubstituteNameOffset = cpu_to_le16(plen); 59 buf->SubstituteNameLength = cpu_to_le16(plen); 60 memcpy(&buf->PathBuffer[plen], path, plen); 61 buf->PrintNameOffset = 0; 62 buf->PrintNameLength = cpu_to_le16(plen); 63 memcpy(buf->PathBuffer, path, plen); 64 buf->Flags = cpu_to_le32(*symname != '/' ? SYMLINK_FLAG_RELATIVE : 0); 65 if (*sym != sep) 66 buf->Flags = cpu_to_le32(SYMLINK_FLAG_RELATIVE); 67 68 convert_delimiter(sym, '/'); 69 iov.iov_base = buf; 70 iov.iov_len = len; 71 new = smb2_get_reparse_inode(&data, inode->i_sb, xid, 72 tcon, full_path, &iov, NULL); 73 if (!IS_ERR(new)) 74 d_instantiate(dentry, new); 75 else 76 rc = PTR_ERR(new); 77 out: 78 kfree(path); 79 cifs_free_open_info(&data); 80 kfree(buf); 81 return rc; 82 } 83 84 static int nfs_set_reparse_buf(struct reparse_posix_data *buf, 85 mode_t mode, dev_t dev, 86 struct kvec *iov) 87 { 88 u64 type; 89 u16 len, dlen; 90 91 len = sizeof(*buf); 92 93 switch ((type = reparse_mode_nfs_type(mode))) { 94 case NFS_SPECFILE_BLK: 95 case NFS_SPECFILE_CHR: 96 dlen = sizeof(__le64); 97 break; 98 case NFS_SPECFILE_FIFO: 99 case NFS_SPECFILE_SOCK: 100 dlen = 0; 101 break; 102 default: 103 return -EOPNOTSUPP; 104 } 105 106 buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_NFS); 107 buf->Reserved = 0; 108 buf->InodeType = cpu_to_le64(type); 109 buf->ReparseDataLength = cpu_to_le16(len + dlen - 110 sizeof(struct reparse_data_buffer)); 111 *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) | 112 MINOR(dev)); 113 iov->iov_base = buf; 114 iov->iov_len = len + dlen; 115 return 0; 116 } 117 118 static int mknod_nfs(unsigned int xid, struct inode *inode, 119 struct dentry *dentry, struct cifs_tcon *tcon, 120 const char *full_path, umode_t mode, dev_t dev) 121 { 122 struct cifs_open_info_data data; 123 struct reparse_posix_data *p; 124 struct inode *new; 125 struct kvec iov; 126 __u8 buf[sizeof(*p) + sizeof(__le64)]; 127 int rc; 128 129 p = (struct reparse_posix_data *)buf; 130 rc = nfs_set_reparse_buf(p, mode, dev, &iov); 131 if (rc) 132 return rc; 133 134 data = (struct cifs_open_info_data) { 135 .reparse_point = true, 136 .reparse = { .tag = IO_REPARSE_TAG_NFS, .posix = p, }, 137 }; 138 139 new = smb2_get_reparse_inode(&data, inode->i_sb, xid, 140 tcon, full_path, &iov, NULL); 141 if (!IS_ERR(new)) 142 d_instantiate(dentry, new); 143 else 144 rc = PTR_ERR(new); 145 cifs_free_open_info(&data); 146 return rc; 147 } 148 149 static int wsl_set_reparse_buf(struct reparse_data_buffer *buf, 150 mode_t mode, struct kvec *iov) 151 { 152 u32 tag; 153 154 switch ((tag = reparse_mode_wsl_tag(mode))) { 155 case IO_REPARSE_TAG_LX_BLK: 156 case IO_REPARSE_TAG_LX_CHR: 157 case IO_REPARSE_TAG_LX_FIFO: 158 case IO_REPARSE_TAG_AF_UNIX: 159 break; 160 default: 161 return -EOPNOTSUPP; 162 } 163 164 buf->ReparseTag = cpu_to_le32(tag); 165 buf->Reserved = 0; 166 buf->ReparseDataLength = 0; 167 iov->iov_base = buf; 168 iov->iov_len = sizeof(*buf); 169 return 0; 170 } 171 172 static struct smb2_create_ea_ctx *ea_create_context(u32 dlen, size_t *cc_len) 173 { 174 struct smb2_create_ea_ctx *cc; 175 176 *cc_len = round_up(sizeof(*cc) + dlen, 8); 177 cc = kzalloc(*cc_len, GFP_KERNEL); 178 if (!cc) 179 return ERR_PTR(-ENOMEM); 180 181 cc->ctx.NameOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, 182 name)); 183 cc->ctx.NameLength = cpu_to_le16(4); 184 memcpy(cc->name, SMB2_CREATE_EA_BUFFER, strlen(SMB2_CREATE_EA_BUFFER)); 185 cc->ctx.DataOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, ea)); 186 cc->ctx.DataLength = cpu_to_le32(dlen); 187 return cc; 188 } 189 190 struct wsl_xattr { 191 const char *name; 192 __le64 value; 193 u16 size; 194 u32 next; 195 }; 196 197 static int wsl_set_xattrs(struct inode *inode, umode_t _mode, 198 dev_t _dev, struct kvec *iov) 199 { 200 struct smb2_file_full_ea_info *ea; 201 struct smb2_create_ea_ctx *cc; 202 struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; 203 __le64 uid = cpu_to_le64(from_kuid(current_user_ns(), ctx->linux_uid)); 204 __le64 gid = cpu_to_le64(from_kgid(current_user_ns(), ctx->linux_gid)); 205 __le64 dev = cpu_to_le64(((u64)MINOR(_dev) << 32) | MAJOR(_dev)); 206 __le64 mode = cpu_to_le64(_mode); 207 struct wsl_xattr xattrs[] = { 208 { .name = SMB2_WSL_XATTR_UID, .value = uid, .size = SMB2_WSL_XATTR_UID_SIZE, }, 209 { .name = SMB2_WSL_XATTR_GID, .value = gid, .size = SMB2_WSL_XATTR_GID_SIZE, }, 210 { .name = SMB2_WSL_XATTR_MODE, .value = mode, .size = SMB2_WSL_XATTR_MODE_SIZE, }, 211 { .name = SMB2_WSL_XATTR_DEV, .value = dev, .size = SMB2_WSL_XATTR_DEV_SIZE, }, 212 }; 213 size_t cc_len; 214 u32 dlen = 0, next = 0; 215 int i, num_xattrs; 216 u8 name_size = SMB2_WSL_XATTR_NAME_LEN + 1; 217 218 memset(iov, 0, sizeof(*iov)); 219 220 /* Exclude $LXDEV xattr for sockets and fifos */ 221 if (S_ISSOCK(_mode) || S_ISFIFO(_mode)) 222 num_xattrs = ARRAY_SIZE(xattrs) - 1; 223 else 224 num_xattrs = ARRAY_SIZE(xattrs); 225 226 for (i = 0; i < num_xattrs; i++) { 227 xattrs[i].next = ALIGN(sizeof(*ea) + name_size + 228 xattrs[i].size, 4); 229 dlen += xattrs[i].next; 230 } 231 232 cc = ea_create_context(dlen, &cc_len); 233 if (IS_ERR(cc)) 234 return PTR_ERR(cc); 235 236 ea = &cc->ea; 237 for (i = 0; i < num_xattrs; i++) { 238 ea = (void *)((u8 *)ea + next); 239 next = xattrs[i].next; 240 ea->next_entry_offset = cpu_to_le32(next); 241 242 ea->ea_name_length = name_size - 1; 243 ea->ea_value_length = cpu_to_le16(xattrs[i].size); 244 memcpy(ea->ea_data, xattrs[i].name, name_size); 245 memcpy(&ea->ea_data[name_size], 246 &xattrs[i].value, xattrs[i].size); 247 } 248 ea->next_entry_offset = 0; 249 250 iov->iov_base = cc; 251 iov->iov_len = cc_len; 252 return 0; 253 } 254 255 static int mknod_wsl(unsigned int xid, struct inode *inode, 256 struct dentry *dentry, struct cifs_tcon *tcon, 257 const char *full_path, umode_t mode, dev_t dev) 258 { 259 struct cifs_open_info_data data; 260 struct reparse_data_buffer buf; 261 struct smb2_create_ea_ctx *cc; 262 struct inode *new; 263 unsigned int len; 264 struct kvec reparse_iov, xattr_iov; 265 int rc; 266 267 rc = wsl_set_reparse_buf(&buf, mode, &reparse_iov); 268 if (rc) 269 return rc; 270 271 rc = wsl_set_xattrs(inode, mode, dev, &xattr_iov); 272 if (rc) 273 return rc; 274 275 data = (struct cifs_open_info_data) { 276 .reparse_point = true, 277 .reparse = { .tag = le32_to_cpu(buf.ReparseTag), .buf = &buf, }, 278 }; 279 280 cc = xattr_iov.iov_base; 281 len = le32_to_cpu(cc->ctx.DataLength); 282 memcpy(data.wsl.eas, &cc->ea, len); 283 data.wsl.eas_len = len; 284 285 new = smb2_get_reparse_inode(&data, inode->i_sb, 286 xid, tcon, full_path, 287 &reparse_iov, &xattr_iov); 288 if (!IS_ERR(new)) 289 d_instantiate(dentry, new); 290 else 291 rc = PTR_ERR(new); 292 cifs_free_open_info(&data); 293 kfree(xattr_iov.iov_base); 294 return rc; 295 } 296 297 int smb2_mknod_reparse(unsigned int xid, struct inode *inode, 298 struct dentry *dentry, struct cifs_tcon *tcon, 299 const char *full_path, umode_t mode, dev_t dev) 300 { 301 struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; 302 int rc = -EOPNOTSUPP; 303 304 switch (ctx->reparse_type) { 305 case CIFS_REPARSE_TYPE_NFS: 306 rc = mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev); 307 break; 308 case CIFS_REPARSE_TYPE_WSL: 309 rc = mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev); 310 break; 311 } 312 return rc; 313 } 314 315 /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ 316 static int parse_reparse_posix(struct reparse_posix_data *buf, 317 struct cifs_sb_info *cifs_sb, 318 struct cifs_open_info_data *data) 319 { 320 unsigned int len; 321 u64 type; 322 323 switch ((type = le64_to_cpu(buf->InodeType))) { 324 case NFS_SPECFILE_LNK: 325 len = le16_to_cpu(buf->ReparseDataLength); 326 data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer, 327 len, true, 328 cifs_sb->local_nls); 329 if (!data->symlink_target) 330 return -ENOMEM; 331 convert_delimiter(data->symlink_target, '/'); 332 cifs_dbg(FYI, "%s: target path: %s\n", 333 __func__, data->symlink_target); 334 break; 335 case NFS_SPECFILE_CHR: 336 case NFS_SPECFILE_BLK: 337 case NFS_SPECFILE_FIFO: 338 case NFS_SPECFILE_SOCK: 339 break; 340 default: 341 cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n", 342 __func__, type); 343 return -EOPNOTSUPP; 344 } 345 return 0; 346 } 347 348 static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym, 349 u32 plen, bool unicode, 350 struct cifs_sb_info *cifs_sb, 351 struct cifs_open_info_data *data) 352 { 353 unsigned int len; 354 unsigned int offs; 355 356 /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ 357 358 offs = le16_to_cpu(sym->SubstituteNameOffset); 359 len = le16_to_cpu(sym->SubstituteNameLength); 360 if (offs + 20 > plen || offs + len + 20 > plen) { 361 cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); 362 return -EIO; 363 } 364 365 data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs, 366 len, unicode, 367 cifs_sb->local_nls); 368 if (!data->symlink_target) 369 return -ENOMEM; 370 371 convert_delimiter(data->symlink_target, '/'); 372 cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target); 373 374 return 0; 375 } 376 377 int parse_reparse_point(struct reparse_data_buffer *buf, 378 u32 plen, struct cifs_sb_info *cifs_sb, 379 bool unicode, struct cifs_open_info_data *data) 380 { 381 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 382 383 data->reparse.buf = buf; 384 385 /* See MS-FSCC 2.1.2 */ 386 switch (le32_to_cpu(buf->ReparseTag)) { 387 case IO_REPARSE_TAG_NFS: 388 return parse_reparse_posix((struct reparse_posix_data *)buf, 389 cifs_sb, data); 390 case IO_REPARSE_TAG_SYMLINK: 391 return parse_reparse_symlink( 392 (struct reparse_symlink_data_buffer *)buf, 393 plen, unicode, cifs_sb, data); 394 case IO_REPARSE_TAG_LX_SYMLINK: 395 case IO_REPARSE_TAG_AF_UNIX: 396 case IO_REPARSE_TAG_LX_FIFO: 397 case IO_REPARSE_TAG_LX_CHR: 398 case IO_REPARSE_TAG_LX_BLK: 399 break; 400 default: 401 cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", 402 le32_to_cpu(buf->ReparseTag)); 403 break; 404 } 405 return 0; 406 } 407 408 int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, 409 struct kvec *rsp_iov, 410 struct cifs_open_info_data *data) 411 { 412 struct reparse_data_buffer *buf; 413 struct smb2_ioctl_rsp *io = rsp_iov->iov_base; 414 u32 plen = le32_to_cpu(io->OutputCount); 415 416 buf = (struct reparse_data_buffer *)((u8 *)io + 417 le32_to_cpu(io->OutputOffset)); 418 return parse_reparse_point(buf, plen, cifs_sb, true, data); 419 } 420 421 static void wsl_to_fattr(struct cifs_open_info_data *data, 422 struct cifs_sb_info *cifs_sb, 423 u32 tag, struct cifs_fattr *fattr) 424 { 425 struct smb2_file_full_ea_info *ea; 426 u32 next = 0; 427 428 switch (tag) { 429 case IO_REPARSE_TAG_LX_SYMLINK: 430 fattr->cf_mode |= S_IFLNK; 431 break; 432 case IO_REPARSE_TAG_LX_FIFO: 433 fattr->cf_mode |= S_IFIFO; 434 break; 435 case IO_REPARSE_TAG_AF_UNIX: 436 fattr->cf_mode |= S_IFSOCK; 437 break; 438 case IO_REPARSE_TAG_LX_CHR: 439 fattr->cf_mode |= S_IFCHR; 440 break; 441 case IO_REPARSE_TAG_LX_BLK: 442 fattr->cf_mode |= S_IFBLK; 443 break; 444 } 445 446 if (!data->wsl.eas_len) 447 goto out; 448 449 ea = (struct smb2_file_full_ea_info *)data->wsl.eas; 450 do { 451 const char *name; 452 void *v; 453 u8 nlen; 454 455 ea = (void *)((u8 *)ea + next); 456 next = le32_to_cpu(ea->next_entry_offset); 457 if (!le16_to_cpu(ea->ea_value_length)) 458 continue; 459 460 name = ea->ea_data; 461 nlen = ea->ea_name_length; 462 v = (void *)((u8 *)ea->ea_data + ea->ea_name_length + 1); 463 464 if (!strncmp(name, SMB2_WSL_XATTR_UID, nlen)) 465 fattr->cf_uid = wsl_make_kuid(cifs_sb, v); 466 else if (!strncmp(name, SMB2_WSL_XATTR_GID, nlen)) 467 fattr->cf_gid = wsl_make_kgid(cifs_sb, v); 468 else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) 469 fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v); 470 else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) 471 fattr->cf_rdev = wsl_mkdev(v); 472 } while (next); 473 out: 474 fattr->cf_dtype = S_DT(fattr->cf_mode); 475 } 476 477 bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, 478 struct cifs_fattr *fattr, 479 struct cifs_open_info_data *data) 480 { 481 struct reparse_posix_data *buf = data->reparse.posix; 482 u32 tag = data->reparse.tag; 483 484 if (tag == IO_REPARSE_TAG_NFS && buf) { 485 switch (le64_to_cpu(buf->InodeType)) { 486 case NFS_SPECFILE_CHR: 487 fattr->cf_mode |= S_IFCHR; 488 fattr->cf_rdev = reparse_nfs_mkdev(buf); 489 break; 490 case NFS_SPECFILE_BLK: 491 fattr->cf_mode |= S_IFBLK; 492 fattr->cf_rdev = reparse_nfs_mkdev(buf); 493 break; 494 case NFS_SPECFILE_FIFO: 495 fattr->cf_mode |= S_IFIFO; 496 break; 497 case NFS_SPECFILE_SOCK: 498 fattr->cf_mode |= S_IFSOCK; 499 break; 500 case NFS_SPECFILE_LNK: 501 fattr->cf_mode |= S_IFLNK; 502 break; 503 default: 504 WARN_ON_ONCE(1); 505 return false; 506 } 507 goto out; 508 } 509 510 switch (tag) { 511 case IO_REPARSE_TAG_INTERNAL: 512 if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY)) 513 return false; 514 fallthrough; 515 case IO_REPARSE_TAG_DFS: 516 case IO_REPARSE_TAG_DFSR: 517 case IO_REPARSE_TAG_MOUNT_POINT: 518 /* See cifs_create_junction_fattr() */ 519 fattr->cf_mode = S_IFDIR | 0711; 520 break; 521 case IO_REPARSE_TAG_LX_SYMLINK: 522 case IO_REPARSE_TAG_LX_FIFO: 523 case IO_REPARSE_TAG_AF_UNIX: 524 case IO_REPARSE_TAG_LX_CHR: 525 case IO_REPARSE_TAG_LX_BLK: 526 wsl_to_fattr(data, cifs_sb, tag, fattr); 527 break; 528 case 0: /* SMB1 symlink */ 529 case IO_REPARSE_TAG_SYMLINK: 530 case IO_REPARSE_TAG_NFS: 531 fattr->cf_mode |= S_IFLNK; 532 break; 533 default: 534 return false; 535 } 536 out: 537 fattr->cf_dtype = S_DT(fattr->cf_mode); 538 return true; 539 } 540