Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.0-rc2 449 lines 13 kB view raw
1/* 2 * fs/cifs/smb2inode.c 3 * 4 * Copyright (C) International Business Machines Corp., 2002, 2011 5 * Etersoft, 2012 6 * Author(s): Pavel Shilovsky (pshilovsky@samba.org), 7 * Steve French (sfrench@us.ibm.com) 8 * 9 * This library is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public License as published 11 * by the Free Software Foundation; either version 2.1 of the License, or 12 * (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 17 * the GNU Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public License 20 * along with this library; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23#include <linux/fs.h> 24#include <linux/stat.h> 25#include <linux/slab.h> 26#include <linux/pagemap.h> 27#include <asm/div64.h> 28#include "cifsfs.h" 29#include "cifspdu.h" 30#include "cifsglob.h" 31#include "cifsproto.h" 32#include "cifs_debug.h" 33#include "cifs_fs_sb.h" 34#include "cifs_unicode.h" 35#include "fscache.h" 36#include "smb2glob.h" 37#include "smb2pdu.h" 38#include "smb2proto.h" 39 40static int 41smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 42 struct cifs_sb_info *cifs_sb, const char *full_path, 43 __u32 desired_access, __u32 create_disposition, 44 __u32 create_options, void *ptr, int command) 45{ 46 int rc; 47 __le16 *utf16_path = NULL; 48 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 49 struct cifs_open_parms oparms; 50 struct cifs_fid fid; 51 struct cifs_ses *ses = tcon->ses; 52 int num_rqst = 0; 53 struct smb_rqst rqst[3]; 54 int resp_buftype[3]; 55 struct kvec rsp_iov[3]; 56 struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; 57 struct kvec qi_iov[1]; 58 struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; 59 struct kvec close_iov[1]; 60 struct smb2_query_info_rsp *qi_rsp = NULL; 61 int flags = 0; 62 __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0}; 63 unsigned int size[2]; 64 void *data[2]; 65 struct smb2_file_rename_info rename_info; 66 struct smb2_file_link_info link_info; 67 int len; 68 69 if (smb3_encryption_required(tcon)) 70 flags |= CIFS_TRANSFORM_REQ; 71 72 memset(rqst, 0, sizeof(rqst)); 73 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; 74 memset(rsp_iov, 0, sizeof(rsp_iov)); 75 76 /* Open */ 77 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); 78 if (!utf16_path) 79 return -ENOMEM; 80 81 oparms.tcon = tcon; 82 oparms.desired_access = desired_access; 83 oparms.disposition = create_disposition; 84 oparms.create_options = create_options; 85 if (backup_cred(cifs_sb)) 86 oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; 87 oparms.fid = &fid; 88 oparms.reconnect = false; 89 90 memset(&open_iov, 0, sizeof(open_iov)); 91 rqst[num_rqst].rq_iov = open_iov; 92 rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE; 93 rc = SMB2_open_init(tcon, &rqst[num_rqst], &oplock, &oparms, 94 utf16_path); 95 kfree(utf16_path); 96 if (rc) 97 goto finished; 98 99 smb2_set_next_command(tcon, &rqst[num_rqst++]); 100 101 /* Operation */ 102 switch (command) { 103 case SMB2_OP_QUERY_INFO: 104 memset(&qi_iov, 0, sizeof(qi_iov)); 105 rqst[num_rqst].rq_iov = qi_iov; 106 rqst[num_rqst].rq_nvec = 1; 107 108 rc = SMB2_query_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 109 COMPOUND_FID, FILE_ALL_INFORMATION, 110 SMB2_O_INFO_FILE, 0, 111 sizeof(struct smb2_file_all_info) + 112 PATH_MAX * 2, 0, NULL); 113 smb2_set_next_command(tcon, &rqst[num_rqst]); 114 smb2_set_related(&rqst[num_rqst++]); 115 break; 116 case SMB2_OP_DELETE: 117 break; 118 case SMB2_OP_MKDIR: 119 /* 120 * Directories are created through parameters in the 121 * SMB2_open() call. 122 */ 123 break; 124 case SMB2_OP_RMDIR: 125 memset(&si_iov, 0, sizeof(si_iov)); 126 rqst[num_rqst].rq_iov = si_iov; 127 rqst[num_rqst].rq_nvec = 1; 128 129 size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ 130 data[0] = &delete_pending[0]; 131 132 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 133 COMPOUND_FID, current->tgid, 134 FILE_DISPOSITION_INFORMATION, 135 SMB2_O_INFO_FILE, 0, data, size); 136 smb2_set_next_command(tcon, &rqst[num_rqst]); 137 smb2_set_related(&rqst[num_rqst++]); 138 break; 139 case SMB2_OP_SET_EOF: 140 memset(&si_iov, 0, sizeof(si_iov)); 141 rqst[num_rqst].rq_iov = si_iov; 142 rqst[num_rqst].rq_nvec = 1; 143 144 size[0] = 8; /* sizeof __le64 */ 145 data[0] = ptr; 146 147 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 148 COMPOUND_FID, current->tgid, 149 FILE_END_OF_FILE_INFORMATION, 150 SMB2_O_INFO_FILE, 0, data, size); 151 smb2_set_next_command(tcon, &rqst[num_rqst]); 152 smb2_set_related(&rqst[num_rqst++]); 153 break; 154 case SMB2_OP_SET_INFO: 155 memset(&si_iov, 0, sizeof(si_iov)); 156 rqst[num_rqst].rq_iov = si_iov; 157 rqst[num_rqst].rq_nvec = 1; 158 159 160 size[0] = sizeof(FILE_BASIC_INFO); 161 data[0] = ptr; 162 163 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 164 COMPOUND_FID, current->tgid, 165 FILE_BASIC_INFORMATION, 166 SMB2_O_INFO_FILE, 0, data, size); 167 smb2_set_next_command(tcon, &rqst[num_rqst]); 168 smb2_set_related(&rqst[num_rqst++]); 169 break; 170 case SMB2_OP_RENAME: 171 memset(&si_iov, 0, sizeof(si_iov)); 172 rqst[num_rqst].rq_iov = si_iov; 173 rqst[num_rqst].rq_nvec = 2; 174 175 len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX)); 176 177 rename_info.ReplaceIfExists = 1; 178 rename_info.RootDirectory = 0; 179 rename_info.FileNameLength = cpu_to_le32(len); 180 181 size[0] = sizeof(struct smb2_file_rename_info); 182 data[0] = &rename_info; 183 184 size[1] = len + 2 /* null */; 185 data[1] = (__le16 *)ptr; 186 187 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 188 COMPOUND_FID, current->tgid, 189 FILE_RENAME_INFORMATION, 190 SMB2_O_INFO_FILE, 0, data, size); 191 smb2_set_next_command(tcon, &rqst[num_rqst]); 192 smb2_set_related(&rqst[num_rqst++]); 193 break; 194 case SMB2_OP_HARDLINK: 195 memset(&si_iov, 0, sizeof(si_iov)); 196 rqst[num_rqst].rq_iov = si_iov; 197 rqst[num_rqst].rq_nvec = 2; 198 199 len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX)); 200 201 link_info.ReplaceIfExists = 0; 202 link_info.RootDirectory = 0; 203 link_info.FileNameLength = cpu_to_le32(len); 204 205 size[0] = sizeof(struct smb2_file_link_info); 206 data[0] = &link_info; 207 208 size[1] = len + 2 /* null */; 209 data[1] = (__le16 *)ptr; 210 211 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 212 COMPOUND_FID, current->tgid, 213 FILE_LINK_INFORMATION, 214 SMB2_O_INFO_FILE, 0, data, size); 215 smb2_set_next_command(tcon, &rqst[num_rqst]); 216 smb2_set_related(&rqst[num_rqst++]); 217 break; 218 default: 219 cifs_dbg(VFS, "Invalid command\n"); 220 rc = -EINVAL; 221 } 222 if (rc) 223 goto finished; 224 225 /* Close */ 226 memset(&close_iov, 0, sizeof(close_iov)); 227 rqst[num_rqst].rq_iov = close_iov; 228 rqst[num_rqst].rq_nvec = 1; 229 rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, 230 COMPOUND_FID); 231 smb2_set_related(&rqst[num_rqst++]); 232 if (rc) 233 goto finished; 234 235 rc = compound_send_recv(xid, ses, flags, num_rqst, rqst, 236 resp_buftype, rsp_iov); 237 238 finished: 239 SMB2_open_free(&rqst[0]); 240 switch (command) { 241 case SMB2_OP_QUERY_INFO: 242 if (rc == 0) { 243 qi_rsp = (struct smb2_query_info_rsp *) 244 rsp_iov[1].iov_base; 245 rc = smb2_validate_and_copy_iov( 246 le16_to_cpu(qi_rsp->OutputBufferOffset), 247 le32_to_cpu(qi_rsp->OutputBufferLength), 248 &rsp_iov[1], sizeof(struct smb2_file_all_info), 249 ptr); 250 } 251 if (rqst[1].rq_iov) 252 SMB2_query_info_free(&rqst[1]); 253 if (rqst[2].rq_iov) 254 SMB2_close_free(&rqst[2]); 255 break; 256 case SMB2_OP_DELETE: 257 case SMB2_OP_MKDIR: 258 if (rqst[1].rq_iov) 259 SMB2_close_free(&rqst[1]); 260 break; 261 case SMB2_OP_HARDLINK: 262 case SMB2_OP_RENAME: 263 case SMB2_OP_RMDIR: 264 case SMB2_OP_SET_EOF: 265 case SMB2_OP_SET_INFO: 266 if (rqst[1].rq_iov) 267 SMB2_set_info_free(&rqst[1]); 268 if (rqst[2].rq_iov) 269 SMB2_close_free(&rqst[2]); 270 break; 271 } 272 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 273 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 274 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); 275 return rc; 276} 277 278void 279move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src) 280{ 281 memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src); 282 dst->CurrentByteOffset = src->CurrentByteOffset; 283 dst->Mode = src->Mode; 284 dst->AlignmentRequirement = src->AlignmentRequirement; 285 dst->IndexNumber1 = 0; /* we don't use it */ 286} 287 288int 289smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 290 struct cifs_sb_info *cifs_sb, const char *full_path, 291 FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink) 292{ 293 int rc; 294 struct smb2_file_all_info *smb2_data; 295 __u32 create_options = 0; 296 297 *adjust_tz = false; 298 *symlink = false; 299 300 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 301 GFP_KERNEL); 302 if (smb2_data == NULL) 303 return -ENOMEM; 304 if (backup_cred(cifs_sb)) 305 create_options |= CREATE_OPEN_BACKUP_INTENT; 306 307 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 308 FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, 309 smb2_data, SMB2_OP_QUERY_INFO); 310 if (rc == -EOPNOTSUPP) { 311 *symlink = true; 312 create_options |= OPEN_REPARSE_POINT; 313 314 /* Failed on a symbolic link - query a reparse point info */ 315 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 316 FILE_READ_ATTRIBUTES, FILE_OPEN, 317 create_options, smb2_data, 318 SMB2_OP_QUERY_INFO); 319 } 320 if (rc) 321 goto out; 322 323 move_smb2_info_to_cifs(data, smb2_data); 324out: 325 kfree(smb2_data); 326 return rc; 327} 328 329int 330smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, 331 struct cifs_sb_info *cifs_sb) 332{ 333 return smb2_compound_op(xid, tcon, cifs_sb, name, 334 FILE_WRITE_ATTRIBUTES, FILE_CREATE, 335 CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR); 336} 337 338void 339smb2_mkdir_setinfo(struct inode *inode, const char *name, 340 struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon, 341 const unsigned int xid) 342{ 343 FILE_BASIC_INFO data; 344 struct cifsInodeInfo *cifs_i; 345 u32 dosattrs; 346 int tmprc; 347 348 memset(&data, 0, sizeof(data)); 349 cifs_i = CIFS_I(inode); 350 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; 351 data.Attributes = cpu_to_le32(dosattrs); 352 tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, 353 FILE_WRITE_ATTRIBUTES, FILE_CREATE, 354 CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO); 355 if (tmprc == 0) 356 cifs_i->cifsAttrs = dosattrs; 357} 358 359int 360smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, 361 struct cifs_sb_info *cifs_sb) 362{ 363 return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 364 CREATE_NOT_FILE, 365 NULL, SMB2_OP_RMDIR); 366} 367 368int 369smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, 370 struct cifs_sb_info *cifs_sb) 371{ 372 return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 373 CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, 374 NULL, SMB2_OP_DELETE); 375} 376 377static int 378smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, 379 const char *from_name, const char *to_name, 380 struct cifs_sb_info *cifs_sb, __u32 access, int command) 381{ 382 __le16 *smb2_to_name = NULL; 383 int rc; 384 385 smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb); 386 if (smb2_to_name == NULL) { 387 rc = -ENOMEM; 388 goto smb2_rename_path; 389 } 390 rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access, 391 FILE_OPEN, 0, smb2_to_name, command); 392smb2_rename_path: 393 kfree(smb2_to_name); 394 return rc; 395} 396 397int 398smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon, 399 const char *from_name, const char *to_name, 400 struct cifs_sb_info *cifs_sb) 401{ 402 return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, 403 DELETE, SMB2_OP_RENAME); 404} 405 406int 407smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, 408 const char *from_name, const char *to_name, 409 struct cifs_sb_info *cifs_sb) 410{ 411 return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, 412 FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK); 413} 414 415int 416smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, 417 const char *full_path, __u64 size, 418 struct cifs_sb_info *cifs_sb, bool set_alloc) 419{ 420 __le64 eof = cpu_to_le64(size); 421 422 return smb2_compound_op(xid, tcon, cifs_sb, full_path, 423 FILE_WRITE_DATA, FILE_OPEN, 0, &eof, 424 SMB2_OP_SET_EOF); 425} 426 427int 428smb2_set_file_info(struct inode *inode, const char *full_path, 429 FILE_BASIC_INFO *buf, const unsigned int xid) 430{ 431 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 432 struct tcon_link *tlink; 433 int rc; 434 435 if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) && 436 (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) && 437 (buf->Attributes == 0)) 438 return 0; /* would be a no op, no sense sending this */ 439 440 tlink = cifs_sb_tlink(cifs_sb); 441 if (IS_ERR(tlink)) 442 return PTR_ERR(tlink); 443 444 rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path, 445 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, 446 SMB2_OP_SET_INFO); 447 cifs_put_tlink(tlink); 448 return rc; 449}