Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '6.1-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull more cifs updates from Steve French:

- fix a regression in guest mounts to old servers

- improvements to directory leasing (caching directory entries safely
beyond the root directory)

- symlink improvement (reducing roundtrips needed to process symlinks)

- an lseek fix (to problem where some dir entries could be skipped)

- improved ioctl for returning more detailed information on directory
change notifications

- clarify multichannel interface query warning

- cleanup fix (for better aligning buffers using ALIGN and round_up)

- a compounding fix

- fix some uninitialized variable bugs found by Coverity and the kernel
test robot

* tag '6.1-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
smb3: improve SMB3 change notification support
cifs: lease key is uninitialized in two additional functions when smb1
cifs: lease key is uninitialized in smb1 paths
smb3: must initialize two ACL struct fields to zero
cifs: fix double-fault crash during ntlmssp
cifs: fix static checker warning
cifs: use ALIGN() and round_up() macros
cifs: find and use the dentry for cached non-root directories also
cifs: enable caching of directories for which a lease is held
cifs: prevent copying past input buffer boundaries
cifs: fix uninitialised var in smb2_compound_op()
cifs: improve symlink handling for smb2+
smb3: clarify multichannel warning
cifs: fix regression in very old smb1 mounts
cifs: fix skipping to incorrect offset in emit_cached_dirents

+921 -725
+283 -184
fs/cifs/cached_dir.c
··· 5 5 * Copyright (c) 2022, Ronnie Sahlberg <lsahlber@redhat.com> 6 6 */ 7 7 8 + #include <linux/namei.h> 8 9 #include "cifsglob.h" 9 10 #include "cifsproto.h" 10 11 #include "cifs_debug.h" 11 12 #include "smb2proto.h" 12 13 #include "cached_dir.h" 13 14 14 - struct cached_fid *init_cached_dir(const char *path); 15 + static struct cached_fid *init_cached_dir(const char *path); 16 + static void free_cached_dir(struct cached_fid *cfid); 17 + 18 + static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, 19 + const char *path, 20 + bool lookup_only) 21 + { 22 + struct cached_fid *cfid; 23 + 24 + spin_lock(&cfids->cfid_list_lock); 25 + list_for_each_entry(cfid, &cfids->entries, entry) { 26 + if (!strcmp(cfid->path, path)) { 27 + /* 28 + * If it doesn't have a lease it is either not yet 29 + * fully cached or it may be in the process of 30 + * being deleted due to a lease break. 31 + */ 32 + if (!cfid->has_lease) { 33 + spin_unlock(&cfids->cfid_list_lock); 34 + return NULL; 35 + } 36 + kref_get(&cfid->refcount); 37 + spin_unlock(&cfids->cfid_list_lock); 38 + return cfid; 39 + } 40 + } 41 + if (lookup_only) { 42 + spin_unlock(&cfids->cfid_list_lock); 43 + return NULL; 44 + } 45 + if (cfids->num_entries >= MAX_CACHED_FIDS) { 46 + spin_unlock(&cfids->cfid_list_lock); 47 + return NULL; 48 + } 49 + cfid = init_cached_dir(path); 50 + if (cfid == NULL) { 51 + spin_unlock(&cfids->cfid_list_lock); 52 + return NULL; 53 + } 54 + cfid->cfids = cfids; 55 + cfids->num_entries++; 56 + list_add(&cfid->entry, &cfids->entries); 57 + cfid->on_list = true; 58 + kref_get(&cfid->refcount); 59 + spin_unlock(&cfids->cfid_list_lock); 60 + return cfid; 61 + } 62 + 63 + static struct dentry * 64 + path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path) 65 + { 66 + struct dentry *dentry; 67 + const char *s, *p; 68 + char sep; 69 + 70 + sep = CIFS_DIR_SEP(cifs_sb); 71 + dentry = dget(cifs_sb->root); 72 + s = path; 73 + 74 + do { 75 + struct inode *dir = d_inode(dentry); 76 + struct dentry *child; 77 + 78 + if (!S_ISDIR(dir->i_mode)) { 79 + dput(dentry); 80 + dentry = ERR_PTR(-ENOTDIR); 81 + break; 82 + } 83 + 84 + /* skip separators */ 85 + while (*s == sep) 86 + s++; 87 + if (!*s) 88 + break; 89 + p = s++; 90 + /* next separator */ 91 + while (*s && *s != sep) 92 + s++; 93 + 94 + child = lookup_positive_unlocked(p, dentry, s - p); 95 + dput(dentry); 96 + dentry = child; 97 + } while (!IS_ERR(dentry)); 98 + return dentry; 99 + } 15 100 16 101 /* 17 102 * Open the and cache a directory handle. ··· 118 33 struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; 119 34 struct kvec qi_iov[1]; 120 35 int rc, flags = 0; 121 - __le16 utf16_path = 0; /* Null - since an open of top of share */ 36 + __le16 *utf16_path = NULL; 122 37 u8 oplock = SMB2_OPLOCK_LEVEL_II; 123 38 struct cifs_fid *pfid; 124 - struct dentry *dentry; 39 + struct dentry *dentry = NULL; 125 40 struct cached_fid *cfid; 41 + struct cached_fids *cfids; 126 42 127 - if (tcon == NULL || tcon->nohandlecache || 43 + if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache || 128 44 is_smb1_server(tcon->ses->server)) 129 45 return -EOPNOTSUPP; 130 46 131 47 ses = tcon->ses; 132 48 server = ses->server; 49 + cfids = tcon->cfids; 50 + 51 + if (!server->ops->new_lease_key) 52 + return -EIO; 133 53 134 54 if (cifs_sb->root == NULL) 135 55 return -ENOENT; 136 56 137 - if (!path[0]) 138 - dentry = cifs_sb->root; 139 - else 140 - return -ENOENT; 141 - 142 - cfid = tcon->cfids->cfid; 143 - if (cfid == NULL) { 144 - cfid = init_cached_dir(path); 145 - tcon->cfids->cfid = cfid; 146 - } 147 - if (cfid == NULL) 57 + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 58 + if (!utf16_path) 148 59 return -ENOMEM; 149 60 150 - mutex_lock(&cfid->fid_mutex); 151 - if (cfid->is_valid) { 152 - cifs_dbg(FYI, "found a cached root file handle\n"); 61 + cfid = find_or_create_cached_dir(cfids, path, lookup_only); 62 + if (cfid == NULL) { 63 + kfree(utf16_path); 64 + return -ENOENT; 65 + } 66 + /* 67 + * At this point we either have a lease already and we can just 68 + * return it. If not we are guaranteed to be the only thread accessing 69 + * this cfid. 70 + */ 71 + if (cfid->has_lease) { 153 72 *ret_cfid = cfid; 154 - kref_get(&cfid->refcount); 155 - mutex_unlock(&cfid->fid_mutex); 73 + kfree(utf16_path); 156 74 return 0; 157 75 } 158 76 159 77 /* 160 78 * We do not hold the lock for the open because in case 161 - * SMB2_open needs to reconnect, it will end up calling 162 - * cifs_mark_open_files_invalid() which takes the lock again 163 - * thus causing a deadlock 79 + * SMB2_open needs to reconnect. 80 + * This is safe because no other thread will be able to get a ref 81 + * to the cfid until we have finished opening the file and (possibly) 82 + * acquired a lease. 164 83 */ 165 - mutex_unlock(&cfid->fid_mutex); 166 - 167 - if (lookup_only) 168 - return -ENOENT; 169 - 170 84 if (smb3_encryption_required(tcon)) 171 85 flags |= CIFS_TRANSFORM_REQ; 172 - 173 - if (!server->ops->new_lease_key) 174 - return -EIO; 175 86 176 87 pfid = &cfid->fid; 177 88 server->ops->new_lease_key(pfid); ··· 189 108 oparms.reconnect = false; 190 109 191 110 rc = SMB2_open_init(tcon, server, 192 - &rqst[0], &oplock, &oparms, &utf16_path); 111 + &rqst[0], &oplock, &oparms, utf16_path); 193 112 if (rc) 194 113 goto oshr_free; 195 114 smb2_set_next_command(tcon, &rqst[0]); ··· 212 131 rc = compound_send_recv(xid, ses, server, 213 132 flags, 2, rqst, 214 133 resp_buftype, rsp_iov); 215 - mutex_lock(&cfid->fid_mutex); 216 - 217 - /* 218 - * Now we need to check again as the cached root might have 219 - * been successfully re-opened from a concurrent process 220 - */ 221 - 222 - if (cfid->is_valid) { 223 - /* work was already done */ 224 - 225 - /* stash fids for close() later */ 226 - struct cifs_fid fid = { 227 - .persistent_fid = pfid->persistent_fid, 228 - .volatile_fid = pfid->volatile_fid, 229 - }; 230 - 231 - /* 232 - * caller expects this func to set the fid in cfid to valid 233 - * cached root, so increment the refcount. 234 - */ 235 - kref_get(&cfid->refcount); 236 - 237 - mutex_unlock(&cfid->fid_mutex); 238 - 239 - if (rc == 0) { 240 - /* close extra handle outside of crit sec */ 241 - SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 242 - } 243 - rc = 0; 244 - goto oshr_free; 245 - } 246 - 247 - /* Cached root is still invalid, continue normaly */ 248 - 249 134 if (rc) { 250 135 if (rc == -EREMCHG) { 251 136 tcon->need_reconnect = true; 252 137 pr_warn_once("server share %s deleted\n", 253 138 tcon->tree_name); 254 139 } 255 - goto oshr_exit; 140 + goto oshr_free; 256 141 } 257 142 258 143 atomic_inc(&tcon->num_remote_opens); ··· 230 183 oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId); 231 184 #endif /* CIFS_DEBUG2 */ 232 185 233 - cfid->tcon = tcon; 234 - cfid->is_valid = true; 235 - cfid->dentry = dentry; 236 - if (dentry) 237 - dget(dentry); 238 - kref_init(&cfid->refcount); 186 + if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) 187 + goto oshr_free; 239 188 240 - /* BB TBD check to see if oplock level check can be removed below */ 241 - if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) { 242 - /* 243 - * See commit 2f94a3125b87. Increment the refcount when we 244 - * get a lease for root, release it if lease break occurs 245 - */ 246 - kref_get(&cfid->refcount); 247 - cfid->has_lease = true; 248 - smb2_parse_contexts(server, o_rsp, 249 - &oparms.fid->epoch, 250 - oparms.fid->lease_key, &oplock, 251 - NULL, NULL); 252 - } else 253 - goto oshr_exit; 189 + 190 + smb2_parse_contexts(server, o_rsp, 191 + &oparms.fid->epoch, 192 + oparms.fid->lease_key, &oplock, 193 + NULL, NULL); 254 194 255 195 qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; 256 196 if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info)) 257 - goto oshr_exit; 197 + goto oshr_free; 258 198 if (!smb2_validate_and_copy_iov( 259 199 le16_to_cpu(qi_rsp->OutputBufferOffset), 260 200 sizeof(struct smb2_file_all_info), ··· 249 215 (char *)&cfid->file_all_info)) 250 216 cfid->file_all_info_is_valid = true; 251 217 218 + if (!path[0]) 219 + dentry = dget(cifs_sb->root); 220 + else { 221 + dentry = path_to_dentry(cifs_sb, path); 222 + if (IS_ERR(dentry)) 223 + goto oshr_free; 224 + } 225 + cfid->dentry = dentry; 226 + cfid->tcon = tcon; 252 227 cfid->time = jiffies; 228 + cfid->is_open = true; 229 + cfid->has_lease = true; 253 230 254 - oshr_exit: 255 - mutex_unlock(&cfid->fid_mutex); 256 231 oshr_free: 232 + kfree(utf16_path); 257 233 SMB2_open_free(&rqst[0]); 258 234 SMB2_query_info_free(&rqst[1]); 259 235 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 260 236 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 237 + spin_lock(&cfids->cfid_list_lock); 238 + if (!cfid->has_lease) { 239 + if (cfid->on_list) { 240 + list_del(&cfid->entry); 241 + cfid->on_list = false; 242 + cfids->num_entries--; 243 + } 244 + rc = -ENOENT; 245 + } 246 + spin_unlock(&cfids->cfid_list_lock); 247 + if (rc) { 248 + free_cached_dir(cfid); 249 + cfid = NULL; 250 + } 251 + 261 252 if (rc == 0) 262 253 *ret_cfid = cfid; 263 254 ··· 294 235 struct cached_fid **ret_cfid) 295 236 { 296 237 struct cached_fid *cfid; 238 + struct cached_fids *cfids = tcon->cfids; 297 239 298 - cfid = tcon->cfids->cfid; 299 - if (cfid == NULL) 240 + if (cfids == NULL) 300 241 return -ENOENT; 301 242 302 - mutex_lock(&cfid->fid_mutex); 303 - if (cfid->dentry == dentry) { 304 - cifs_dbg(FYI, "found a cached root file handle by dentry\n"); 305 - *ret_cfid = cfid; 306 - kref_get(&cfid->refcount); 307 - mutex_unlock(&cfid->fid_mutex); 308 - return 0; 243 + spin_lock(&cfids->cfid_list_lock); 244 + list_for_each_entry(cfid, &cfids->entries, entry) { 245 + if (dentry && cfid->dentry == dentry) { 246 + cifs_dbg(FYI, "found a cached root file handle by dentry\n"); 247 + kref_get(&cfid->refcount); 248 + *ret_cfid = cfid; 249 + spin_unlock(&cfids->cfid_list_lock); 250 + return 0; 251 + } 309 252 } 310 - mutex_unlock(&cfid->fid_mutex); 253 + spin_unlock(&cfids->cfid_list_lock); 311 254 return -ENOENT; 312 255 } 313 256 ··· 318 257 { 319 258 struct cached_fid *cfid = container_of(ref, struct cached_fid, 320 259 refcount); 321 - struct cached_dirent *dirent, *q; 322 260 323 - if (cfid->is_valid) { 324 - cifs_dbg(FYI, "clear cached root file handle\n"); 261 + spin_lock(&cfid->cfids->cfid_list_lock); 262 + if (cfid->on_list) { 263 + list_del(&cfid->entry); 264 + cfid->on_list = false; 265 + cfid->cfids->num_entries--; 266 + } 267 + spin_unlock(&cfid->cfids->cfid_list_lock); 268 + 269 + dput(cfid->dentry); 270 + cfid->dentry = NULL; 271 + 272 + if (cfid->is_open) { 325 273 SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, 326 274 cfid->fid.volatile_fid); 327 275 } 328 276 329 - /* 330 - * We only check validity above to send SMB2_close, 331 - * but we still need to invalidate these entries 332 - * when this function is called 333 - */ 334 - cfid->is_valid = false; 335 - cfid->file_all_info_is_valid = false; 336 - cfid->has_lease = false; 337 - if (cfid->dentry) { 338 - dput(cfid->dentry); 339 - cfid->dentry = NULL; 340 - } 341 - /* 342 - * Delete all cached dirent names 343 - */ 344 - mutex_lock(&cfid->dirents.de_mutex); 345 - list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) { 346 - list_del(&dirent->entry); 347 - kfree(dirent->name); 348 - kfree(dirent); 349 - } 350 - cfid->dirents.is_valid = 0; 351 - cfid->dirents.is_failed = 0; 352 - cfid->dirents.ctx = NULL; 353 - cfid->dirents.pos = 0; 354 - mutex_unlock(&cfid->dirents.de_mutex); 355 - 277 + free_cached_dir(cfid); 356 278 } 357 279 358 280 void close_cached_dir(struct cached_fid *cfid) 359 281 { 360 - mutex_lock(&cfid->fid_mutex); 361 282 kref_put(&cfid->refcount, smb2_close_cached_fid); 362 - mutex_unlock(&cfid->fid_mutex); 363 - } 364 - 365 - void close_cached_dir_lease_locked(struct cached_fid *cfid) 366 - { 367 - if (cfid->has_lease) { 368 - cfid->has_lease = false; 369 - kref_put(&cfid->refcount, smb2_close_cached_fid); 370 - } 371 - } 372 - 373 - void close_cached_dir_lease(struct cached_fid *cfid) 374 - { 375 - mutex_lock(&cfid->fid_mutex); 376 - close_cached_dir_lease_locked(cfid); 377 - mutex_unlock(&cfid->fid_mutex); 378 283 } 379 284 380 285 /* ··· 353 326 struct cached_fid *cfid; 354 327 struct cifs_tcon *tcon; 355 328 struct tcon_link *tlink; 329 + struct cached_fids *cfids; 356 330 357 331 for (node = rb_first(root); node; node = rb_next(node)) { 358 332 tlink = rb_entry(node, struct tcon_link, tl_rbnode); 359 333 tcon = tlink_tcon(tlink); 360 334 if (IS_ERR(tcon)) 361 335 continue; 362 - cfid = tcon->cfids->cfid; 363 - if (cfid == NULL) 336 + cfids = tcon->cfids; 337 + if (cfids == NULL) 364 338 continue; 365 - mutex_lock(&cfid->fid_mutex); 366 - if (cfid->dentry) { 339 + list_for_each_entry(cfid, &cfids->entries, entry) { 367 340 dput(cfid->dentry); 368 341 cfid->dentry = NULL; 369 342 } 370 - mutex_unlock(&cfid->fid_mutex); 371 343 } 372 344 } 373 345 374 346 /* 375 - * Invalidate and close all cached dirs when a TCON has been reset 347 + * Invalidate all cached dirs when a TCON has been reset 376 348 * due to a session loss. 377 349 */ 378 350 void invalidate_all_cached_dirs(struct cifs_tcon *tcon) 379 351 { 380 - struct cached_fid *cfid = tcon->cfids->cfid; 352 + struct cached_fids *cfids = tcon->cfids; 353 + struct cached_fid *cfid, *q; 354 + struct list_head entry; 381 355 382 - if (cfid == NULL) 383 - return; 356 + INIT_LIST_HEAD(&entry); 357 + spin_lock(&cfids->cfid_list_lock); 358 + list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { 359 + list_del(&cfid->entry); 360 + list_add(&cfid->entry, &entry); 361 + cfids->num_entries--; 362 + cfid->is_open = false; 363 + /* To prevent race with smb2_cached_lease_break() */ 364 + kref_get(&cfid->refcount); 365 + } 366 + spin_unlock(&cfids->cfid_list_lock); 384 367 385 - mutex_lock(&cfid->fid_mutex); 386 - cfid->is_valid = false; 387 - /* cached handle is not valid, so SMB2_CLOSE won't be sent below */ 388 - close_cached_dir_lease_locked(cfid); 389 - memset(&cfid->fid, 0, sizeof(struct cifs_fid)); 390 - mutex_unlock(&cfid->fid_mutex); 368 + list_for_each_entry_safe(cfid, q, &entry, entry) { 369 + cfid->on_list = false; 370 + list_del(&cfid->entry); 371 + cancel_work_sync(&cfid->lease_break); 372 + if (cfid->has_lease) { 373 + /* 374 + * We lease was never cancelled from the server so we 375 + * need to drop the reference. 376 + */ 377 + spin_lock(&cfids->cfid_list_lock); 378 + cfid->has_lease = false; 379 + spin_unlock(&cfids->cfid_list_lock); 380 + kref_put(&cfid->refcount, smb2_close_cached_fid); 381 + } 382 + /* Drop the extra reference opened above*/ 383 + kref_put(&cfid->refcount, smb2_close_cached_fid); 384 + } 391 385 } 392 386 393 387 static void ··· 417 369 struct cached_fid *cfid = container_of(work, 418 370 struct cached_fid, lease_break); 419 371 420 - close_cached_dir_lease(cfid); 372 + spin_lock(&cfid->cfids->cfid_list_lock); 373 + cfid->has_lease = false; 374 + spin_unlock(&cfid->cfids->cfid_list_lock); 375 + kref_put(&cfid->refcount, smb2_close_cached_fid); 421 376 } 422 377 423 378 int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]) 424 379 { 425 - struct cached_fid *cfid = tcon->cfids->cfid; 380 + struct cached_fids *cfids = tcon->cfids; 381 + struct cached_fid *cfid; 426 382 427 - if (cfid == NULL) 383 + if (cfids == NULL) 428 384 return false; 429 385 430 - if (cfid->is_valid && 431 - !memcmp(lease_key, 432 - cfid->fid.lease_key, 433 - SMB2_LEASE_KEY_SIZE)) { 434 - cfid->time = 0; 435 - INIT_WORK(&cfid->lease_break, 436 - smb2_cached_lease_break); 437 - queue_work(cifsiod_wq, 438 - &cfid->lease_break); 439 - return true; 386 + spin_lock(&cfids->cfid_list_lock); 387 + list_for_each_entry(cfid, &cfids->entries, entry) { 388 + if (cfid->has_lease && 389 + !memcmp(lease_key, 390 + cfid->fid.lease_key, 391 + SMB2_LEASE_KEY_SIZE)) { 392 + cfid->time = 0; 393 + /* 394 + * We found a lease remove it from the list 395 + * so no threads can access it. 396 + */ 397 + list_del(&cfid->entry); 398 + cfid->on_list = false; 399 + cfids->num_entries--; 400 + 401 + queue_work(cifsiod_wq, 402 + &cfid->lease_break); 403 + spin_unlock(&cfids->cfid_list_lock); 404 + return true; 405 + } 440 406 } 407 + spin_unlock(&cfids->cfid_list_lock); 441 408 return false; 442 409 } 443 410 444 - struct cached_fid *init_cached_dir(const char *path) 411 + static struct cached_fid *init_cached_dir(const char *path) 445 412 { 446 413 struct cached_fid *cfid; 447 414 448 - cfid = kzalloc(sizeof(*cfid), GFP_KERNEL); 415 + cfid = kzalloc(sizeof(*cfid), GFP_ATOMIC); 449 416 if (!cfid) 450 417 return NULL; 451 - cfid->path = kstrdup(path, GFP_KERNEL); 418 + cfid->path = kstrdup(path, GFP_ATOMIC); 452 419 if (!cfid->path) { 453 420 kfree(cfid); 454 421 return NULL; 455 422 } 456 423 424 + INIT_WORK(&cfid->lease_break, smb2_cached_lease_break); 425 + INIT_LIST_HEAD(&cfid->entry); 457 426 INIT_LIST_HEAD(&cfid->dirents.entries); 458 427 mutex_init(&cfid->dirents.de_mutex); 459 - mutex_init(&cfid->fid_mutex); 428 + spin_lock_init(&cfid->fid_lock); 429 + kref_init(&cfid->refcount); 460 430 return cfid; 461 431 } 462 432 463 - void free_cached_dir(struct cached_fid *cfid) 433 + static void free_cached_dir(struct cached_fid *cfid) 464 434 { 435 + struct cached_dirent *dirent, *q; 436 + 437 + dput(cfid->dentry); 438 + cfid->dentry = NULL; 439 + 440 + /* 441 + * Delete all cached dirent names 442 + */ 443 + list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) { 444 + list_del(&dirent->entry); 445 + kfree(dirent->name); 446 + kfree(dirent); 447 + } 448 + 465 449 kfree(cfid->path); 466 450 cfid->path = NULL; 467 451 kfree(cfid); ··· 506 426 cfids = kzalloc(sizeof(*cfids), GFP_KERNEL); 507 427 if (!cfids) 508 428 return NULL; 509 - mutex_init(&cfids->cfid_list_mutex); 429 + spin_lock_init(&cfids->cfid_list_lock); 430 + INIT_LIST_HEAD(&cfids->entries); 510 431 return cfids; 511 432 } 512 433 434 + /* 435 + * Called from tconInfoFree when we are tearing down the tcon. 436 + * There are no active users or open files/directories at this point. 437 + */ 513 438 void free_cached_dirs(struct cached_fids *cfids) 514 439 { 515 - if (cfids->cfid) { 516 - free_cached_dir(cfids->cfid); 517 - cfids->cfid = NULL; 440 + struct cached_fid *cfid, *q; 441 + struct list_head entry; 442 + 443 + INIT_LIST_HEAD(&entry); 444 + spin_lock(&cfids->cfid_list_lock); 445 + list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { 446 + cfid->on_list = false; 447 + cfid->is_open = false; 448 + list_del(&cfid->entry); 449 + list_add(&cfid->entry, &entry); 518 450 } 451 + spin_unlock(&cfids->cfid_list_lock); 452 + 453 + list_for_each_entry_safe(cfid, q, &entry, entry) { 454 + list_del(&cfid->entry); 455 + free_cached_dir(cfid); 456 + } 457 + 519 458 kfree(cfids); 520 459 }
+13 -7
fs/cifs/cached_dir.h
··· 31 31 }; 32 32 33 33 struct cached_fid { 34 + struct list_head entry; 35 + struct cached_fids *cfids; 34 36 const char *path; 35 - bool is_valid:1; /* Do we have a useable root fid */ 36 - bool file_all_info_is_valid:1; 37 37 bool has_lease:1; 38 + bool is_open:1; 39 + bool on_list:1; 40 + bool file_all_info_is_valid:1; 38 41 unsigned long time; /* jiffies of when lease was taken */ 39 42 struct kref refcount; 40 43 struct cifs_fid fid; 41 - struct mutex fid_mutex; 44 + spinlock_t fid_lock; 42 45 struct cifs_tcon *tcon; 43 46 struct dentry *dentry; 44 47 struct work_struct lease_break; ··· 49 46 struct cached_dirents dirents; 50 47 }; 51 48 49 + #define MAX_CACHED_FIDS 16 52 50 struct cached_fids { 53 - struct mutex cfid_list_mutex; 54 - struct cached_fid *cfid; 51 + /* Must be held when: 52 + * - accessing the cfids->entries list 53 + */ 54 + spinlock_t cfid_list_lock; 55 + int num_entries; 56 + struct list_head entries; 55 57 }; 56 58 57 59 extern struct cached_fids *init_cached_dirs(void); ··· 69 61 struct dentry *dentry, 70 62 struct cached_fid **cfid); 71 63 extern void close_cached_dir(struct cached_fid *cfid); 72 - extern void close_cached_dir_lease(struct cached_fid *cfid); 73 - extern void close_cached_dir_lease_locked(struct cached_fid *cfid); 74 64 extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb); 75 65 extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon); 76 66 extern int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
+8
fs/cifs/cifs_ioctl.h
··· 91 91 bool watch_tree; 92 92 } __packed; 93 93 94 + struct smb3_notify_info { 95 + __u32 completion_filter; 96 + bool watch_tree; 97 + __u32 data_len; /* size of notify data below */ 98 + __u8 notify_data[]; 99 + } __packed; 100 + 94 101 #define CIFS_IOCTL_MAGIC 0xCF 95 102 #define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) 96 103 #define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4) ··· 107 100 #define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info) 108 101 #define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify) 109 102 #define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info) 103 + #define CIFS_IOC_NOTIFY_INFO _IOWR(CIFS_IOCTL_MAGIC, 11, struct smb3_notify_info) 110 104 #define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32) 111 105 112 106 /*
+7 -2
fs/cifs/cifsfs.c
··· 396 396 cifs_inode->epoch = 0; 397 397 spin_lock_init(&cifs_inode->open_file_lock); 398 398 generate_random_uuid(cifs_inode->lease_key); 399 + cifs_inode->symlink_target = NULL; 399 400 400 401 /* 401 402 * Can not set i_flags here - they get immediately overwritten to zero ··· 413 412 static void 414 413 cifs_free_inode(struct inode *inode) 415 414 { 416 - kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); 415 + struct cifsInodeInfo *cinode = CIFS_I(inode); 416 + 417 + if (S_ISLNK(inode->i_mode)) 418 + kfree(cinode->symlink_target); 419 + kmem_cache_free(cifs_inode_cachep, cinode); 417 420 } 418 421 419 422 static void ··· 1144 1139 }; 1145 1140 1146 1141 const struct inode_operations cifs_symlink_inode_ops = { 1147 - .get_link = cifs_get_link, 1142 + .get_link = simple_get_link, 1148 1143 .permission = cifs_permission, 1149 1144 .listxattr = cifs_listxattr, 1150 1145 };
+37 -11
fs/cifs/cifsglob.h
··· 185 185 struct cifs_ace *aces; 186 186 }; 187 187 188 + struct cifs_open_info_data { 189 + char *symlink_target; 190 + union { 191 + struct smb2_file_all_info fi; 192 + struct smb311_posix_qinfo posix_fi; 193 + }; 194 + }; 195 + 196 + static inline void cifs_free_open_info(struct cifs_open_info_data *data) 197 + { 198 + kfree(data->symlink_target); 199 + } 200 + 188 201 /* 189 202 ***************************************************************** 190 203 * Except the CIFS PDUs themselves all the ··· 320 307 int (*is_path_accessible)(const unsigned int, struct cifs_tcon *, 321 308 struct cifs_sb_info *, const char *); 322 309 /* query path data from the server */ 323 - int (*query_path_info)(const unsigned int, struct cifs_tcon *, 324 - struct cifs_sb_info *, const char *, 325 - FILE_ALL_INFO *, bool *, bool *); 310 + int (*query_path_info)(const unsigned int xid, struct cifs_tcon *tcon, 311 + struct cifs_sb_info *cifs_sb, const char *full_path, 312 + struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse); 326 313 /* query file data from the server */ 327 - int (*query_file_info)(const unsigned int, struct cifs_tcon *, 328 - struct cifs_fid *, FILE_ALL_INFO *); 314 + int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon, 315 + struct cifsFileInfo *cfile, struct cifs_open_info_data *data); 329 316 /* query reparse tag from srv to determine which type of special file */ 330 317 int (*query_reparse_tag)(const unsigned int xid, struct cifs_tcon *tcon, 331 318 struct cifs_sb_info *cifs_sb, const char *path, 332 319 __u32 *reparse_tag); 333 320 /* get server index number */ 334 - int (*get_srv_inum)(const unsigned int, struct cifs_tcon *, 335 - struct cifs_sb_info *, const char *, 336 - u64 *uniqueid, FILE_ALL_INFO *); 321 + int (*get_srv_inum)(const unsigned int xid, struct cifs_tcon *tcon, 322 + struct cifs_sb_info *cifs_sb, const char *full_path, u64 *uniqueid, 323 + struct cifs_open_info_data *data); 337 324 /* set size by path */ 338 325 int (*set_path_size)(const unsigned int, struct cifs_tcon *, 339 326 const char *, __u64, struct cifs_sb_info *, bool); ··· 382 369 struct cifs_sb_info *, const char *, 383 370 char **, bool); 384 371 /* open a file for non-posix mounts */ 385 - int (*open)(const unsigned int, struct cifs_open_parms *, 386 - __u32 *, FILE_ALL_INFO *); 372 + int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, 373 + void *buf); 387 374 /* set fid protocol-specific info */ 388 375 void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32); 389 376 /* close a file */ ··· 454 441 int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon, 455 442 struct cifsFileInfo *src_file, void __user *); 456 443 int (*notify)(const unsigned int xid, struct file *pfile, 457 - void __user *pbuf); 444 + void __user *pbuf, bool return_changes); 458 445 int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, 459 446 struct cifs_sb_info *, const unsigned char *, 460 447 char *, unsigned int *); ··· 1136 1123 struct timespec64 cf_mtime; 1137 1124 struct timespec64 cf_ctime; 1138 1125 u32 cf_cifstag; 1126 + char *cf_symlink_target; 1139 1127 }; 1140 1128 1141 1129 /* ··· 1399 1385 struct work_struct put; /* work for the final part of _put */ 1400 1386 struct delayed_work deferred; 1401 1387 bool deferred_close_scheduled; /* Flag to indicate close is scheduled */ 1388 + char *symlink_target; 1402 1389 }; 1403 1390 1404 1391 struct cifs_io_parms { ··· 1558 1543 struct list_head deferred_closes; /* list of deferred closes */ 1559 1544 spinlock_t deferred_lock; /* protection on deferred list */ 1560 1545 bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */ 1546 + char *symlink_target; 1561 1547 }; 1562 1548 1563 1549 static inline struct cifsInodeInfo * ··· 2125 2109 if (ses->server->dialect <= SMB20_PROT_ID) 2126 2110 return min_t(size_t, sizeof(ses->workstation_name), RFC1001_NAME_LEN_WITH_NULL); 2127 2111 return sizeof(ses->workstation_name); 2112 + } 2113 + 2114 + static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const FILE_ALL_INFO *src) 2115 + { 2116 + memcpy(dst, src, (size_t)((u8 *)&src->AccessFlags - (u8 *)src)); 2117 + dst->AccessFlags = src->AccessFlags; 2118 + dst->CurrentByteOffset = src->CurrentByteOffset; 2119 + dst->Mode = src->Mode; 2120 + dst->AlignmentRequirement = src->AlignmentRequirement; 2121 + dst->FileNameLength = src->FileNameLength; 2128 2122 } 2129 2123 2130 2124 #endif /* _CIFS_GLOB_H */
+6 -7
fs/cifs/cifsproto.h
··· 182 182 extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile); 183 183 184 184 extern void cifs_down_write(struct rw_semaphore *sem); 185 - extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, 186 - struct file *file, 187 - struct tcon_link *tlink, 188 - __u32 oplock); 185 + struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, 186 + struct tcon_link *tlink, __u32 oplock, 187 + const char *symlink_target); 189 188 extern int cifs_posix_open(const char *full_path, struct inode **inode, 190 189 struct super_block *sb, int mode, 191 190 unsigned int f_flags, __u32 *oplock, __u16 *netfid, ··· 199 200 extern struct inode *cifs_iget(struct super_block *sb, 200 201 struct cifs_fattr *fattr); 201 202 202 - extern int cifs_get_inode_info(struct inode **inode, const char *full_path, 203 - FILE_ALL_INFO *data, struct super_block *sb, 204 - int xid, const struct cifs_fid *fid); 203 + int cifs_get_inode_info(struct inode **inode, const char *full_path, 204 + struct cifs_open_info_data *data, struct super_block *sb, int xid, 205 + const struct cifs_fid *fid); 205 206 extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path, 206 207 struct super_block *sb, unsigned int xid); 207 208 extern int cifs_get_inode_info_unix(struct inode **pinode,
+1 -1
fs/cifs/cifssmb.c
··· 2305 2305 remap); 2306 2306 } 2307 2307 rename_info->target_name_len = cpu_to_le32(2 * len_of_str); 2308 - count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str); 2308 + count = sizeof(struct set_file_rename) + (2 * len_of_str); 2309 2309 byte_count += count; 2310 2310 pSMB->DataCount = cpu_to_le16(count); 2311 2311 pSMB->TotalDataCount = pSMB->DataCount;
+14 -8
fs/cifs/connect.c
··· 2832 2832 * sessinit is sent but no second negprot 2833 2833 */ 2834 2834 struct rfc1002_session_packet *ses_init_buf; 2835 + unsigned int req_noscope_len; 2835 2836 struct smb_hdr *smb_buf; 2837 + 2836 2838 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), 2837 2839 GFP_KERNEL); 2840 + 2838 2841 if (ses_init_buf) { 2839 2842 ses_init_buf->trailer.session_req.called_len = 32; 2840 2843 ··· 2873 2870 ses_init_buf->trailer.session_req.scope2 = 0; 2874 2871 smb_buf = (struct smb_hdr *)ses_init_buf; 2875 2872 2876 - /* sizeof RFC1002_SESSION_REQUEST with no scope */ 2877 - smb_buf->smb_buf_length = cpu_to_be32(0x81000044); 2873 + /* sizeof RFC1002_SESSION_REQUEST with no scopes */ 2874 + req_noscope_len = sizeof(struct rfc1002_session_packet) - 2; 2875 + 2876 + /* == cpu_to_be32(0x81000044) */ 2877 + smb_buf->smb_buf_length = 2878 + cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | req_noscope_len); 2878 2879 rc = smb_send(server, smb_buf, 0x44); 2879 2880 kfree(ses_init_buf); 2880 2881 /* ··· 3929 3922 pSMB->AndXCommand = 0xFF; 3930 3923 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); 3931 3924 bcc_ptr = &pSMB->Password[0]; 3932 - if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) { 3933 - pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ 3934 - *bcc_ptr = 0; /* password is null byte */ 3935 - bcc_ptr++; /* skip password */ 3936 - /* already aligned so no need to do it below */ 3937 - } 3925 + 3926 + pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ 3927 + *bcc_ptr = 0; /* password is null byte */ 3928 + bcc_ptr++; /* skip password */ 3929 + /* already aligned so no need to do it below */ 3938 3930 3939 3931 if (ses->server->sign) 3940 3932 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+12 -20
fs/cifs/dir.c
··· 165 165 166 166 /* Inode operations in similar order to how they appear in Linux file fs.h */ 167 167 168 - static int 169 - cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, 170 - struct tcon_link *tlink, unsigned oflags, umode_t mode, 171 - __u32 *oplock, struct cifs_fid *fid) 168 + static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, 169 + struct tcon_link *tlink, unsigned int oflags, umode_t mode, __u32 *oplock, 170 + struct cifs_fid *fid, struct cifs_open_info_data *buf) 172 171 { 173 172 int rc = -ENOENT; 174 173 int create_options = CREATE_NOT_DIR; ··· 176 177 struct cifs_tcon *tcon = tlink_tcon(tlink); 177 178 const char *full_path; 178 179 void *page = alloc_dentry_path(); 179 - FILE_ALL_INFO *buf = NULL; 180 180 struct inode *newinode = NULL; 181 181 int disposition; 182 182 struct TCP_Server_Info *server = tcon->ses->server; ··· 288 290 goto out; 289 291 } 290 292 291 - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 292 - if (buf == NULL) { 293 - rc = -ENOMEM; 294 - goto out; 295 - } 296 - 297 293 /* 298 294 * if we're not using unix extensions, see if we need to set 299 295 * ATTR_READONLY on the create call ··· 356 364 { 357 365 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 358 366 /* TODO: Add support for calling POSIX query info here, but passing in fid */ 359 - rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, 360 - xid, fid); 367 + rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, xid, fid); 361 368 if (newinode) { 362 369 if (server->ops->set_lease_key) 363 370 server->ops->set_lease_key(newinode, fid); ··· 393 402 d_add(direntry, newinode); 394 403 395 404 out: 396 - kfree(buf); 397 405 free_dentry_path(page); 398 406 return rc; 399 407 ··· 413 423 struct tcon_link *tlink; 414 424 struct cifs_tcon *tcon; 415 425 struct TCP_Server_Info *server; 416 - struct cifs_fid fid; 426 + struct cifs_fid fid = {}; 417 427 struct cifs_pending_open open; 418 428 __u32 oplock; 419 429 struct cifsFileInfo *file_info; 430 + struct cifs_open_info_data buf = {}; 420 431 421 432 if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb)))) 422 433 return -EIO; ··· 475 484 cifs_add_pending_open(&fid, tlink, &open); 476 485 477 486 rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, 478 - &oplock, &fid); 479 - 487 + &oplock, &fid, &buf); 480 488 if (rc) { 481 489 cifs_del_pending_open(&open); 482 490 goto out; ··· 500 510 file->f_op = &cifs_file_direct_ops; 501 511 } 502 512 503 - file_info = cifs_new_fileinfo(&fid, file, tlink, oplock); 513 + file_info = cifs_new_fileinfo(&fid, file, tlink, oplock, buf.symlink_target); 504 514 if (file_info == NULL) { 505 515 if (server->ops->close) 506 516 server->ops->close(xid, tcon, &fid); ··· 516 526 cifs_put_tlink(tlink); 517 527 out_free_xid: 518 528 free_xid(xid); 529 + cifs_free_open_info(&buf); 519 530 return rc; 520 531 } 521 532 ··· 538 547 struct TCP_Server_Info *server; 539 548 struct cifs_fid fid; 540 549 __u32 oplock; 550 + struct cifs_open_info_data buf = {}; 541 551 542 552 cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n", 543 553 inode, direntry, direntry); ··· 557 565 if (server->ops->new_lease_key) 558 566 server->ops->new_lease_key(&fid); 559 567 560 - rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, 561 - &oplock, &fid); 568 + rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fid, &buf); 562 569 if (!rc && server->ops->close) 563 570 server->ops->close(xid, tcon, &fid); 564 571 572 + cifs_free_open_info(&buf); 565 573 cifs_put_tlink(tlink); 566 574 out_free_xid: 567 575 free_xid(xid);
+24 -21
fs/cifs/file.c
··· 209 209 } 210 210 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 211 211 212 - static int 213 - cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, 214 - struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock, 215 - struct cifs_fid *fid, unsigned int xid) 212 + static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, 213 + struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock, 214 + struct cifs_fid *fid, unsigned int xid, struct cifs_open_info_data *buf) 216 215 { 217 216 int rc; 218 217 int desired_access; 219 218 int disposition; 220 219 int create_options = CREATE_NOT_DIR; 221 - FILE_ALL_INFO *buf; 222 220 struct TCP_Server_Info *server = tcon->ses->server; 223 221 struct cifs_open_parms oparms; 224 222 ··· 253 255 254 256 /* BB pass O_SYNC flag through on file attributes .. BB */ 255 257 256 - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 257 - if (!buf) 258 - return -ENOMEM; 259 - 260 258 /* O_SYNC also has bit for O_DSYNC so following check picks up either */ 261 259 if (f_flags & O_SYNC) 262 260 create_options |= CREATE_WRITE_THROUGH; ··· 270 276 oparms.reconnect = false; 271 277 272 278 rc = server->ops->open(xid, &oparms, oplock, buf); 273 - 274 279 if (rc) 275 - goto out; 280 + return rc; 276 281 277 282 /* TODO: Add support for calling posix query info but with passing in fid */ 278 283 if (tcon->unix_ext) ··· 287 294 rc = -EOPENSTALE; 288 295 } 289 296 290 - out: 291 - kfree(buf); 292 297 return rc; 293 298 } 294 299 ··· 316 325 317 326 static void cifsFileInfo_put_work(struct work_struct *work); 318 327 319 - struct cifsFileInfo * 320 - cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, 321 - struct tcon_link *tlink, __u32 oplock) 328 + struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, 329 + struct tcon_link *tlink, __u32 oplock, 330 + const char *symlink_target) 322 331 { 323 332 struct dentry *dentry = file_dentry(file); 324 333 struct inode *inode = d_inode(dentry); ··· 336 345 if (!fdlocks) { 337 346 kfree(cfile); 338 347 return NULL; 348 + } 349 + 350 + if (symlink_target) { 351 + cfile->symlink_target = kstrdup(symlink_target, GFP_KERNEL); 352 + if (!cfile->symlink_target) { 353 + kfree(fdlocks); 354 + kfree(cfile); 355 + return NULL; 356 + } 339 357 } 340 358 341 359 INIT_LIST_HEAD(&fdlocks->locks); ··· 440 440 cifs_put_tlink(cifs_file->tlink); 441 441 dput(cifs_file->dentry); 442 442 cifs_sb_deactive(sb); 443 + kfree(cifs_file->symlink_target); 443 444 kfree(cifs_file); 444 445 } 445 446 ··· 489 488 struct cifsInodeInfo *cifsi = CIFS_I(inode); 490 489 struct super_block *sb = inode->i_sb; 491 490 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 492 - struct cifs_fid fid; 491 + struct cifs_fid fid = {}; 493 492 struct cifs_pending_open open; 494 493 bool oplock_break_cancelled; 495 494 ··· 571 570 void *page; 572 571 const char *full_path; 573 572 bool posix_open_ok = false; 574 - struct cifs_fid fid; 573 + struct cifs_fid fid = {}; 575 574 struct cifs_pending_open open; 575 + struct cifs_open_info_data data = {}; 576 576 577 577 xid = get_xid(); 578 578 ··· 664 662 if (server->ops->get_lease_key) 665 663 server->ops->get_lease_key(inode, &fid); 666 664 667 - rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, 668 - file->f_flags, &oplock, &fid, xid); 665 + rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, file->f_flags, &oplock, &fid, 666 + xid, &data); 669 667 if (rc) { 670 668 cifs_del_pending_open(&open); 671 669 goto out; 672 670 } 673 671 } 674 672 675 - cfile = cifs_new_fileinfo(&fid, file, tlink, oplock); 673 + cfile = cifs_new_fileinfo(&fid, file, tlink, oplock, data.symlink_target); 676 674 if (cfile == NULL) { 677 675 if (server->ops->close) 678 676 server->ops->close(xid, tcon, &fid); ··· 714 712 free_dentry_path(page); 715 713 free_xid(xid); 716 714 cifs_put_tlink(tlink); 715 + cifs_free_open_info(&data); 717 716 return rc; 718 717 } 719 718
+105 -71
fs/cifs/inode.c
··· 210 210 */ 211 211 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; 212 212 } 213 + 214 + if (S_ISLNK(fattr->cf_mode)) { 215 + kfree(cifs_i->symlink_target); 216 + cifs_i->symlink_target = fattr->cf_symlink_target; 217 + fattr->cf_symlink_target = NULL; 218 + 219 + if (unlikely(!cifs_i->symlink_target)) 220 + inode->i_link = ERR_PTR(-EOPNOTSUPP); 221 + else 222 + inode->i_link = cifs_i->symlink_target; 223 + } 213 224 spin_unlock(&inode->i_lock); 214 225 215 226 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL) ··· 358 347 int rc; 359 348 unsigned int xid; 360 349 FILE_UNIX_BASIC_INFO find_data; 361 - struct cifs_fattr fattr; 350 + struct cifs_fattr fattr = {}; 362 351 struct inode *inode = file_inode(filp); 363 352 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 364 353 struct cifsFileInfo *cfile = filp->private_data; 365 354 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 366 355 367 356 xid = get_xid(); 357 + 358 + if (cfile->symlink_target) { 359 + fattr.cf_symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); 360 + if (!fattr.cf_symlink_target) 361 + return -ENOMEM; 362 + } 363 + 368 364 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data); 369 365 if (!rc) { 370 366 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); ··· 396 378 FILE_UNIX_BASIC_INFO find_data; 397 379 struct cifs_fattr fattr; 398 380 struct cifs_tcon *tcon; 381 + struct TCP_Server_Info *server; 399 382 struct tcon_link *tlink; 400 383 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 401 384 ··· 406 387 if (IS_ERR(tlink)) 407 388 return PTR_ERR(tlink); 408 389 tcon = tlink_tcon(tlink); 390 + server = tcon->ses->server; 409 391 410 392 /* could have done a find first instead but this returns more info */ 411 393 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, 412 394 cifs_sb->local_nls, cifs_remap(cifs_sb)); 395 + cifs_dbg(FYI, "%s: query path info: rc = %d\n", __func__, rc); 413 396 cifs_put_tlink(tlink); 414 397 415 398 if (!rc) { ··· 429 408 full_path); 430 409 if (tmprc) 431 410 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); 411 + } 412 + 413 + if (S_ISLNK(fattr.cf_mode) && !fattr.cf_symlink_target) { 414 + if (!server->ops->query_symlink) 415 + return -EOPNOTSUPP; 416 + rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path, 417 + &fattr.cf_symlink_target, false); 418 + if (rc) { 419 + cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc); 420 + goto cgiiu_exit; 421 + } 432 422 } 433 423 434 424 if (*pinode == NULL) { ··· 464 432 } 465 433 466 434 cgiiu_exit: 435 + kfree(fattr.cf_symlink_target); 467 436 return rc; 468 437 } 469 438 #else ··· 634 601 } 635 602 636 603 /* Fill a cifs_fattr struct with info from POSIX info struct */ 637 - static void 638 - smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info, 639 - struct super_block *sb, bool adjust_tz, bool symlink) 604 + static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data, 605 + struct super_block *sb, bool adjust_tz, bool symlink) 640 606 { 607 + struct smb311_posix_qinfo *info = &data->posix_fi; 641 608 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 642 609 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 643 610 ··· 672 639 if (symlink) { 673 640 fattr->cf_mode |= S_IFLNK; 674 641 fattr->cf_dtype = DT_LNK; 642 + fattr->cf_symlink_target = data->symlink_target; 643 + data->symlink_target = NULL; 675 644 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 676 645 fattr->cf_mode |= S_IFDIR; 677 646 fattr->cf_dtype = DT_DIR; ··· 690 655 fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink); 691 656 } 692 657 693 - 694 - /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ 695 - static void 696 - cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, 697 - struct super_block *sb, bool adjust_tz, 698 - bool symlink, u32 reparse_tag) 658 + static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data, 659 + struct super_block *sb, bool adjust_tz, bool symlink, 660 + u32 reparse_tag) 699 661 { 662 + struct smb2_file_all_info *info = &data->fi; 700 663 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 701 664 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 702 665 ··· 736 703 } else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) { 737 704 fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode; 738 705 fattr->cf_dtype = DT_BLK; 739 - } else if (symlink) { /* TODO add more reparse tag checks */ 706 + } else if (symlink || reparse_tag == IO_REPARSE_TAG_SYMLINK || 707 + reparse_tag == IO_REPARSE_TAG_NFS) { 740 708 fattr->cf_mode = S_IFLNK; 741 709 fattr->cf_dtype = DT_LNK; 742 710 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { ··· 769 735 } 770 736 } 771 737 738 + if (S_ISLNK(fattr->cf_mode)) { 739 + fattr->cf_symlink_target = data->symlink_target; 740 + data->symlink_target = NULL; 741 + } 742 + 772 743 fattr->cf_uid = cifs_sb->ctx->linux_uid; 773 744 fattr->cf_gid = cifs_sb->ctx->linux_gid; 774 745 } ··· 783 744 { 784 745 int rc; 785 746 unsigned int xid; 786 - FILE_ALL_INFO find_data; 747 + struct cifs_open_info_data data = {}; 787 748 struct cifs_fattr fattr; 788 749 struct inode *inode = file_inode(filp); 789 750 struct cifsFileInfo *cfile = filp->private_data; 790 751 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 791 752 struct TCP_Server_Info *server = tcon->ses->server; 753 + bool symlink = false; 754 + u32 tag = 0; 792 755 793 756 if (!server->ops->query_file_info) 794 757 return -ENOSYS; 795 758 796 759 xid = get_xid(); 797 - rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data); 760 + rc = server->ops->query_file_info(xid, tcon, cfile, &data); 798 761 switch (rc) { 799 762 case 0: 800 763 /* TODO: add support to query reparse tag */ 801 - cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false, 802 - false, 0 /* no reparse tag */); 764 + if (data.symlink_target) { 765 + symlink = true; 766 + tag = IO_REPARSE_TAG_SYMLINK; 767 + } 768 + cifs_open_info_to_fattr(&fattr, &data, inode->i_sb, false, symlink, tag); 803 769 break; 804 770 case -EREMOTE: 805 771 cifs_create_dfs_fattr(&fattr, inode->i_sb); ··· 833 789 /* if filetype is different, return error */ 834 790 rc = cifs_fattr_to_inode(inode, &fattr); 835 791 cgfi_exit: 792 + cifs_free_open_info(&data); 836 793 free_xid(xid); 837 794 return rc; 838 795 } ··· 905 860 } 906 861 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 907 862 908 - static void 909 - cifs_set_fattr_ino(int xid, 910 - struct cifs_tcon *tcon, 911 - struct super_block *sb, 912 - struct inode **inode, 913 - const char *full_path, 914 - FILE_ALL_INFO *data, 915 - struct cifs_fattr *fattr) 863 + static void cifs_set_fattr_ino(int xid, struct cifs_tcon *tcon, struct super_block *sb, 864 + struct inode **inode, const char *full_path, 865 + struct cifs_open_info_data *data, struct cifs_fattr *fattr) 916 866 { 917 867 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 918 868 struct TCP_Server_Info *server = tcon->ses->server; ··· 925 885 * If we have an inode pass a NULL tcon to ensure we don't 926 886 * make a round trip to the server. This only works for SMB2+. 927 887 */ 928 - rc = server->ops->get_srv_inum(xid, 929 - *inode ? NULL : tcon, 930 - cifs_sb, full_path, 931 - &fattr->cf_uniqueid, 932 - data); 888 + rc = server->ops->get_srv_inum(xid, *inode ? NULL : tcon, cifs_sb, full_path, 889 + &fattr->cf_uniqueid, data); 933 890 if (rc) { 934 891 /* 935 892 * If that fails reuse existing ino or generate one ··· 960 923 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0; 961 924 } 962 925 963 - int 964 - cifs_get_inode_info(struct inode **inode, 965 - const char *full_path, 966 - FILE_ALL_INFO *in_data, 967 - struct super_block *sb, int xid, 968 - const struct cifs_fid *fid) 926 + int cifs_get_inode_info(struct inode **inode, const char *full_path, 927 + struct cifs_open_info_data *data, struct super_block *sb, int xid, 928 + const struct cifs_fid *fid) 969 929 { 970 - 971 930 struct cifs_tcon *tcon; 972 931 struct TCP_Server_Info *server; 973 932 struct tcon_link *tlink; ··· 971 938 bool adjust_tz = false; 972 939 struct cifs_fattr fattr = {0}; 973 940 bool is_reparse_point = false; 974 - FILE_ALL_INFO *data = in_data; 975 - FILE_ALL_INFO *tmp_data = NULL; 941 + struct cifs_open_info_data tmp_data = {}; 976 942 void *smb1_backup_rsp_buf = NULL; 977 943 int rc = 0; 978 944 int tmprc = 0; ··· 992 960 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); 993 961 goto out; 994 962 } 995 - tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 996 - if (!tmp_data) { 997 - rc = -ENOMEM; 998 - goto out; 999 - } 1000 - rc = server->ops->query_path_info(xid, tcon, cifs_sb, 1001 - full_path, tmp_data, 1002 - &adjust_tz, &is_reparse_point); 963 + rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, &tmp_data, 964 + &adjust_tz, &is_reparse_point); 1003 965 #ifdef CONFIG_CIFS_DFS_UPCALL 1004 966 if (rc == -ENOENT && is_tcon_dfs(tcon)) 1005 967 rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, 1006 968 cifs_sb, 1007 969 full_path); 1008 970 #endif 1009 - data = tmp_data; 971 + data = &tmp_data; 1010 972 } 1011 973 1012 974 /* ··· 1014 988 * since we have to check if its reparse tag matches a known 1015 989 * special file type e.g. symlink or fifo or char etc. 1016 990 */ 1017 - if ((le32_to_cpu(data->Attributes) & ATTR_REPARSE) && 1018 - server->ops->query_reparse_tag) { 1019 - rc = server->ops->query_reparse_tag(xid, tcon, cifs_sb, 1020 - full_path, &reparse_tag); 1021 - cifs_dbg(FYI, "reparse tag 0x%x\n", reparse_tag); 991 + if (is_reparse_point && data->symlink_target) { 992 + reparse_tag = IO_REPARSE_TAG_SYMLINK; 993 + } else if ((le32_to_cpu(data->fi.Attributes) & ATTR_REPARSE) && 994 + server->ops->query_reparse_tag) { 995 + tmprc = server->ops->query_reparse_tag(xid, tcon, cifs_sb, full_path, 996 + &reparse_tag); 997 + if (tmprc) 998 + cifs_dbg(FYI, "%s: query_reparse_tag: rc = %d\n", __func__, tmprc); 999 + if (server->ops->query_symlink) { 1000 + tmprc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path, 1001 + &data->symlink_target, 1002 + is_reparse_point); 1003 + if (tmprc) 1004 + cifs_dbg(FYI, "%s: query_symlink: rc = %d\n", __func__, 1005 + tmprc); 1006 + } 1022 1007 } 1023 - cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, 1024 - is_reparse_point, reparse_tag); 1008 + cifs_open_info_to_fattr(&fattr, data, sb, adjust_tz, is_reparse_point, reparse_tag); 1025 1009 break; 1026 1010 case -EREMOTE: 1027 1011 /* DFS link, no metadata available on this server */ ··· 1050 1014 */ 1051 1015 if (backup_cred(cifs_sb) && is_smb1_server(server)) { 1052 1016 /* for easier reading */ 1017 + FILE_ALL_INFO *fi; 1053 1018 FILE_DIRECTORY_INFO *fdi; 1054 1019 SEARCH_ID_FULL_DIR_INFO *si; 1055 1020 1056 1021 rc = cifs_backup_query_path_info(xid, tcon, sb, 1057 1022 full_path, 1058 1023 &smb1_backup_rsp_buf, 1059 - &data); 1024 + &fi); 1060 1025 if (rc) 1061 1026 goto out; 1062 1027 1063 - fdi = (FILE_DIRECTORY_INFO *)data; 1064 - si = (SEARCH_ID_FULL_DIR_INFO *)data; 1028 + move_cifs_info_to_smb2(&data->fi, fi); 1029 + fdi = (FILE_DIRECTORY_INFO *)fi; 1030 + si = (SEARCH_ID_FULL_DIR_INFO *)fi; 1065 1031 1066 1032 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb); 1067 1033 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId); ··· 1161 1123 out: 1162 1124 cifs_buf_release(smb1_backup_rsp_buf); 1163 1125 cifs_put_tlink(tlink); 1164 - kfree(tmp_data); 1126 + cifs_free_open_info(&tmp_data); 1127 + kfree(fattr.cf_symlink_target); 1165 1128 return rc; 1166 1129 } 1167 1130 ··· 1177 1138 bool adjust_tz = false; 1178 1139 struct cifs_fattr fattr = {0}; 1179 1140 bool symlink = false; 1180 - struct smb311_posix_qinfo *data = NULL; 1141 + struct cifs_open_info_data data = {}; 1181 1142 int rc = 0; 1182 1143 int tmprc = 0; 1183 1144 ··· 1194 1155 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); 1195 1156 goto out; 1196 1157 } 1197 - data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL); 1198 - if (!data) { 1199 - rc = -ENOMEM; 1200 - goto out; 1201 - } 1202 1158 1203 - rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, 1204 - full_path, data, 1205 - &adjust_tz, &symlink); 1159 + rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data, &adjust_tz, 1160 + &symlink); 1206 1161 1207 1162 /* 1208 1163 * 2. Convert it to internal cifs metadata (fattr) ··· 1204 1171 1205 1172 switch (rc) { 1206 1173 case 0: 1207 - smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink); 1174 + smb311_posix_info_to_fattr(&fattr, &data, sb, adjust_tz, symlink); 1208 1175 break; 1209 1176 case -EREMOTE: 1210 1177 /* DFS link, no metadata available on this server */ ··· 1261 1228 } 1262 1229 out: 1263 1230 cifs_put_tlink(tlink); 1264 - kfree(data); 1231 + cifs_free_open_info(&data); 1232 + kfree(fattr.cf_symlink_target); 1265 1233 return rc; 1266 1234 } 1267 1235 ··· 2299 2265 return true; 2300 2266 2301 2267 if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) { 2302 - mutex_lock(&cfid->fid_mutex); 2268 + spin_lock(&cfid->fid_lock); 2303 2269 if (cfid->time && cifs_i->time > cfid->time) { 2304 - mutex_unlock(&cfid->fid_mutex); 2270 + spin_unlock(&cfid->fid_lock); 2305 2271 close_cached_dir(cfid); 2306 2272 return false; 2307 2273 } 2308 - mutex_unlock(&cfid->fid_mutex); 2274 + spin_unlock(&cfid->fid_lock); 2309 2275 close_cached_dir(cfid); 2310 2276 } 2311 2277 /*
+24 -1
fs/cifs/ioctl.c
··· 484 484 tcon = tlink_tcon(tlink); 485 485 if (tcon && tcon->ses->server->ops->notify) { 486 486 rc = tcon->ses->server->ops->notify(xid, 487 - filep, (void __user *)arg); 487 + filep, (void __user *)arg, 488 + false /* no ret data */); 488 489 cifs_dbg(FYI, "ioctl notify rc %d\n", rc); 490 + } else 491 + rc = -EOPNOTSUPP; 492 + cifs_put_tlink(tlink); 493 + break; 494 + case CIFS_IOC_NOTIFY_INFO: 495 + if (!S_ISDIR(inode->i_mode)) { 496 + /* Notify can only be done on directories */ 497 + rc = -EOPNOTSUPP; 498 + break; 499 + } 500 + cifs_sb = CIFS_SB(inode->i_sb); 501 + tlink = cifs_sb_tlink(cifs_sb); 502 + if (IS_ERR(tlink)) { 503 + rc = PTR_ERR(tlink); 504 + break; 505 + } 506 + tcon = tlink_tcon(tlink); 507 + if (tcon && tcon->ses->server->ops->notify) { 508 + rc = tcon->ses->server->ops->notify(xid, 509 + filep, (void __user *)arg, 510 + true /* return details */); 511 + cifs_dbg(FYI, "ioctl notify info rc %d\n", rc); 489 512 } else 490 513 rc = -EOPNOTSUPP; 491 514 cifs_put_tlink(tlink);
+3 -104
fs/cifs/link.c
··· 201 201 return rc; 202 202 } 203 203 204 - static int 205 - query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, 206 - struct cifs_sb_info *cifs_sb, const unsigned char *path, 207 - char **symlinkinfo) 208 - { 209 - int rc; 210 - u8 *buf = NULL; 211 - unsigned int link_len = 0; 212 - unsigned int bytes_read = 0; 213 - 214 - buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 215 - if (!buf) 216 - return -ENOMEM; 217 - 218 - if (tcon->ses->server->ops->query_mf_symlink) 219 - rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, 220 - cifs_sb, path, buf, &bytes_read); 221 - else 222 - rc = -ENOSYS; 223 - 224 - if (rc) 225 - goto out; 226 - 227 - if (bytes_read == 0) { /* not a symlink */ 228 - rc = -EINVAL; 229 - goto out; 230 - } 231 - 232 - rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo); 233 - out: 234 - kfree(buf); 235 - return rc; 236 - } 237 - 238 204 int 239 205 check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 240 206 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, ··· 210 244 u8 *buf = NULL; 211 245 unsigned int link_len = 0; 212 246 unsigned int bytes_read = 0; 247 + char *symlink = NULL; 213 248 214 249 if (!couldbe_mf_symlink(fattr)) 215 250 /* it's not a symlink */ ··· 232 265 if (bytes_read == 0) /* not a symlink */ 233 266 goto out; 234 267 235 - rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL); 268 + rc = parse_mf_symlink(buf, bytes_read, &link_len, &symlink); 236 269 if (rc == -EINVAL) { 237 270 /* it's not a symlink */ 238 271 rc = 0; ··· 247 280 fattr->cf_mode &= ~S_IFMT; 248 281 fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; 249 282 fattr->cf_dtype = DT_LNK; 283 + fattr->cf_symlink_target = symlink; 250 284 out: 251 285 kfree(buf); 252 286 return rc; ··· 565 597 free_xid(xid); 566 598 cifs_put_tlink(tlink); 567 599 return rc; 568 - } 569 - 570 - const char * 571 - cifs_get_link(struct dentry *direntry, struct inode *inode, 572 - struct delayed_call *done) 573 - { 574 - int rc = -ENOMEM; 575 - unsigned int xid; 576 - const char *full_path; 577 - void *page; 578 - char *target_path = NULL; 579 - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 580 - struct tcon_link *tlink = NULL; 581 - struct cifs_tcon *tcon; 582 - struct TCP_Server_Info *server; 583 - 584 - if (!direntry) 585 - return ERR_PTR(-ECHILD); 586 - 587 - xid = get_xid(); 588 - 589 - tlink = cifs_sb_tlink(cifs_sb); 590 - if (IS_ERR(tlink)) { 591 - free_xid(xid); 592 - return ERR_CAST(tlink); 593 - } 594 - tcon = tlink_tcon(tlink); 595 - server = tcon->ses->server; 596 - 597 - page = alloc_dentry_path(); 598 - full_path = build_path_from_dentry(direntry, page); 599 - if (IS_ERR(full_path)) { 600 - free_xid(xid); 601 - cifs_put_tlink(tlink); 602 - free_dentry_path(page); 603 - return ERR_CAST(full_path); 604 - } 605 - 606 - cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode); 607 - 608 - rc = -EACCES; 609 - /* 610 - * First try Minshall+French Symlinks, if configured 611 - * and fallback to UNIX Extensions Symlinks. 612 - */ 613 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 614 - rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, 615 - &target_path); 616 - 617 - if (rc != 0 && server->ops->query_symlink) { 618 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 619 - bool reparse_point = false; 620 - 621 - if (cifsi->cifsAttrs & ATTR_REPARSE) 622 - reparse_point = true; 623 - 624 - rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path, 625 - &target_path, reparse_point); 626 - } 627 - 628 - free_dentry_path(page); 629 - free_xid(xid); 630 - cifs_put_tlink(tlink); 631 - if (rc != 0) { 632 - kfree(target_path); 633 - return ERR_PTR(rc); 634 - } 635 - set_delayed_call(done, kfree_link, target_path); 636 - return target_path; 637 600 } 638 601 639 602 int
+25 -6
fs/cifs/readdir.c
··· 844 844 struct dir_context *ctx) 845 845 { 846 846 struct cached_dirent *dirent; 847 - int rc; 847 + bool rc; 848 848 849 849 list_for_each_entry(dirent, &cde->entries, entry) { 850 - if (ctx->pos >= dirent->pos) 850 + /* 851 + * Skip all early entries prior to the current lseek() 852 + * position. 853 + */ 854 + if (ctx->pos > dirent->pos) 851 855 continue; 856 + /* 857 + * We recorded the current ->pos value for the dirent 858 + * when we stored it in the cache. 859 + * However, this sequence of ->pos values may have holes 860 + * in it, for example dot-dirs returned from the server 861 + * are suppressed. 862 + * Handle this bu forcing ctx->pos to be the same as the 863 + * ->pos of the current dirent we emit from the cache. 864 + * This means that when we emit these entries from the cache 865 + * we now emit them with the same ->pos value as in the 866 + * initial scan. 867 + */ 852 868 ctx->pos = dirent->pos; 853 869 rc = dir_emit(ctx, dirent->name, dirent->namelen, 854 870 dirent->fattr.cf_uniqueid, 855 871 dirent->fattr.cf_dtype); 856 872 if (!rc) 857 873 return rc; 874 + ctx->pos++; 858 875 } 859 876 return true; 860 877 } ··· 1011 994 cifs_unix_basic_to_fattr(&fattr, 1012 995 &((FILE_UNIX_INFO *)find_entry)->basic, 1013 996 cifs_sb); 997 + if (S_ISLNK(fattr.cf_mode)) 998 + fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; 1014 999 break; 1015 1000 case SMB_FIND_FILE_INFO_STANDARD: 1016 1001 cifs_std_info_to_fattr(&fattr, ··· 1221 1202 ctx->pos, tmp_buf); 1222 1203 cifs_save_resume_key(current_entry, cifsFile); 1223 1204 break; 1224 - } else 1225 - current_entry = 1226 - nxt_dir_entry(current_entry, end_of_smb, 1227 - cifsFile->srch_inf.info_level); 1205 + } 1206 + current_entry = 1207 + nxt_dir_entry(current_entry, end_of_smb, 1208 + cifsFile->srch_inf.info_level); 1228 1209 } 1229 1210 kfree(tmp_buf); 1230 1211
+15 -19
fs/cifs/sess.c
··· 601 601 /* BB FIXME add check that strings total less 602 602 than 335 or will need to send them as arrays */ 603 603 604 - /* unicode strings, must be word aligned before the call */ 605 - /* if ((long) bcc_ptr % 2) { 606 - *bcc_ptr = 0; 607 - bcc_ptr++; 608 - } */ 609 604 /* copy user */ 610 605 if (ses->user_name == NULL) { 611 606 /* null user mount */ ··· 1208 1213 static void 1209 1214 sess_free_buffer(struct sess_data *sess_data) 1210 1215 { 1211 - int i; 1216 + struct kvec *iov = sess_data->iov; 1212 1217 1213 - /* zero the session data before freeing, as it might contain sensitive info (keys, etc) */ 1214 - for (i = 0; i < 3; i++) 1215 - if (sess_data->iov[i].iov_base) 1216 - memzero_explicit(sess_data->iov[i].iov_base, sess_data->iov[i].iov_len); 1218 + /* 1219 + * Zero the session data before freeing, as it might contain sensitive info (keys, etc). 1220 + * Note that iov[1] is already freed by caller. 1221 + */ 1222 + if (sess_data->buf0_type != CIFS_NO_BUFFER && iov[0].iov_base) 1223 + memzero_explicit(iov[0].iov_base, iov[0].iov_len); 1217 1224 1218 - free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base); 1225 + free_rsp_buf(sess_data->buf0_type, iov[0].iov_base); 1219 1226 sess_data->buf0_type = CIFS_NO_BUFFER; 1220 - kfree(sess_data->iov[2].iov_base); 1227 + kfree_sensitive(iov[2].iov_base); 1221 1228 } 1222 1229 1223 1230 static int ··· 1321 1324 } 1322 1325 1323 1326 if (ses->capabilities & CAP_UNICODE) { 1324 - if (sess_data->iov[0].iov_len % 2) { 1327 + if (!IS_ALIGNED(sess_data->iov[0].iov_len, 2)) { 1325 1328 *bcc_ptr = 0; 1326 1329 bcc_ptr++; 1327 1330 } ··· 1361 1364 /* no string area to decode, do nothing */ 1362 1365 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { 1363 1366 /* unicode string area must be word-aligned */ 1364 - if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { 1367 + if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) { 1365 1368 ++bcc_ptr; 1366 1369 --bytes_remaining; 1367 1370 } ··· 1445 1448 1446 1449 if (ses->capabilities & CAP_UNICODE) { 1447 1450 /* unicode strings must be word aligned */ 1448 - if ((sess_data->iov[0].iov_len 1449 - + sess_data->iov[1].iov_len) % 2) { 1451 + if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) { 1450 1452 *bcc_ptr = 0; 1451 1453 bcc_ptr++; 1452 1454 } ··· 1496 1500 /* no string area to decode, do nothing */ 1497 1501 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { 1498 1502 /* unicode string area must be word-aligned */ 1499 - if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { 1503 + if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) { 1500 1504 ++bcc_ptr; 1501 1505 --bytes_remaining; 1502 1506 } ··· 1548 1552 1549 1553 bcc_ptr = sess_data->iov[2].iov_base; 1550 1554 /* unicode strings must be word aligned */ 1551 - if ((sess_data->iov[0].iov_len + sess_data->iov[1].iov_len) % 2) { 1555 + if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) { 1552 1556 *bcc_ptr = 0; 1553 1557 bcc_ptr++; 1554 1558 } ··· 1749 1753 /* no string area to decode, do nothing */ 1750 1754 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { 1751 1755 /* unicode string area must be word-aligned */ 1752 - if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { 1756 + if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) { 1753 1757 ++bcc_ptr; 1754 1758 --bytes_remaining; 1755 1759 }
+34 -22
fs/cifs/smb1ops.c
··· 542 542 return rc; 543 543 } 544 544 545 - static int 546 - cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 547 - struct cifs_sb_info *cifs_sb, const char *full_path, 548 - FILE_ALL_INFO *data, bool *adjustTZ, bool *symlink) 545 + static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 546 + struct cifs_sb_info *cifs_sb, const char *full_path, 547 + struct cifs_open_info_data *data, bool *adjustTZ, bool *symlink) 549 548 { 550 549 int rc; 550 + FILE_ALL_INFO fi = {}; 551 551 552 552 *symlink = false; 553 553 554 554 /* could do find first instead but this returns more info */ 555 - rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */, 556 - cifs_sb->local_nls, cifs_remap(cifs_sb)); 555 + rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls, 556 + cifs_remap(cifs_sb)); 557 557 /* 558 558 * BB optimize code so we do not make the above call when server claims 559 559 * no NT SMB support and the above call failed at least once - set flag 560 560 * in tcon or mount. 561 561 */ 562 562 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { 563 - rc = SMBQueryInformation(xid, tcon, full_path, data, 564 - cifs_sb->local_nls, 563 + rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls, 565 564 cifs_remap(cifs_sb)); 565 + if (!rc) 566 + move_cifs_info_to_smb2(&data->fi, &fi); 566 567 *adjustTZ = true; 567 568 } 568 569 569 - if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { 570 + if (!rc && (le32_to_cpu(fi.Attributes) & ATTR_REPARSE)) { 570 571 int tmprc; 571 572 int oplock = 0; 572 573 struct cifs_fid fid; ··· 593 592 return rc; 594 593 } 595 594 596 - static int 597 - cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, 598 - struct cifs_sb_info *cifs_sb, const char *full_path, 599 - u64 *uniqueid, FILE_ALL_INFO *data) 595 + static int cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, 596 + struct cifs_sb_info *cifs_sb, const char *full_path, 597 + u64 *uniqueid, struct cifs_open_info_data *unused) 600 598 { 601 599 /* 602 600 * We can not use the IndexNumber field by default from Windows or ··· 613 613 cifs_remap(cifs_sb)); 614 614 } 615 615 616 - static int 617 - cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, 618 - struct cifs_fid *fid, FILE_ALL_INFO *data) 616 + static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, 617 + struct cifsFileInfo *cfile, struct cifs_open_info_data *data) 619 618 { 620 - return CIFSSMBQFileInfo(xid, tcon, fid->netfid, data); 619 + int rc; 620 + FILE_ALL_INFO fi = {}; 621 + 622 + if (cfile->symlink_target) { 623 + data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); 624 + if (!data->symlink_target) 625 + return -ENOMEM; 626 + } 627 + 628 + rc = CIFSSMBQFileInfo(xid, tcon, cfile->fid.netfid, &fi); 629 + if (!rc) 630 + move_cifs_info_to_smb2(&data->fi, &fi); 631 + return rc; 621 632 } 622 633 623 634 static void ··· 713 702 cifsInode->cifsAttrs = dosattrs; 714 703 } 715 704 716 - static int 717 - cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, 718 - __u32 *oplock, FILE_ALL_INFO *buf) 705 + static int cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, 706 + void *buf) 719 707 { 708 + FILE_ALL_INFO *fi = buf; 709 + 720 710 if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS)) 721 711 return SMBLegacyOpen(xid, oparms->tcon, oparms->path, 722 712 oparms->disposition, 723 713 oparms->desired_access, 724 714 oparms->create_options, 725 - &oparms->fid->netfid, oplock, buf, 715 + &oparms->fid->netfid, oplock, fi, 726 716 oparms->cifs_sb->local_nls, 727 717 cifs_remap(oparms->cifs_sb)); 728 - return CIFS_open(xid, oparms, oplock, buf); 718 + return CIFS_open(xid, oparms, oplock, fi); 729 719 } 730 720 731 721 static void
+106 -21
fs/cifs/smb2file.c
··· 20 20 #include "cifs_unicode.h" 21 21 #include "fscache.h" 22 22 #include "smb2proto.h" 23 + #include "smb2status.h" 23 24 24 - int 25 - smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, 26 - __u32 *oplock, FILE_ALL_INFO *buf) 25 + static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov) 26 + { 27 + struct smb2_err_rsp *err = iov->iov_base; 28 + struct smb2_symlink_err_rsp *sym = ERR_PTR(-EINVAL); 29 + u32 len; 30 + 31 + if (err->ErrorContextCount) { 32 + struct smb2_error_context_rsp *p, *end; 33 + 34 + len = (u32)err->ErrorContextCount * (offsetof(struct smb2_error_context_rsp, 35 + ErrorContextData) + 36 + sizeof(struct smb2_symlink_err_rsp)); 37 + if (le32_to_cpu(err->ByteCount) < len || iov->iov_len < len + sizeof(*err)) 38 + return ERR_PTR(-EINVAL); 39 + 40 + p = (struct smb2_error_context_rsp *)err->ErrorData; 41 + end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len); 42 + do { 43 + if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) { 44 + sym = (struct smb2_symlink_err_rsp *)&p->ErrorContextData; 45 + break; 46 + } 47 + cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n", 48 + __func__, le32_to_cpu(p->ErrorId)); 49 + 50 + len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8); 51 + p = (struct smb2_error_context_rsp *)((u8 *)&p->ErrorContextData + len); 52 + } while (p < end); 53 + } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) && 54 + iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) { 55 + sym = (struct smb2_symlink_err_rsp *)err->ErrorData; 56 + } 57 + 58 + if (!IS_ERR(sym) && (le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG || 59 + le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK)) 60 + sym = ERR_PTR(-EINVAL); 61 + 62 + return sym; 63 + } 64 + 65 + int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path) 66 + { 67 + struct smb2_symlink_err_rsp *sym; 68 + unsigned int sub_offs, sub_len; 69 + unsigned int print_offs, print_len; 70 + char *s; 71 + 72 + if (!cifs_sb || !iov || !iov->iov_base || !iov->iov_len || !path) 73 + return -EINVAL; 74 + 75 + sym = symlink_data(iov); 76 + if (IS_ERR(sym)) 77 + return PTR_ERR(sym); 78 + 79 + sub_len = le16_to_cpu(sym->SubstituteNameLength); 80 + sub_offs = le16_to_cpu(sym->SubstituteNameOffset); 81 + print_len = le16_to_cpu(sym->PrintNameLength); 82 + print_offs = le16_to_cpu(sym->PrintNameOffset); 83 + 84 + if (iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offs + sub_len || 85 + iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len) 86 + return -EINVAL; 87 + 88 + s = cifs_strndup_from_utf16((char *)sym->PathBuffer + sub_offs, sub_len, true, 89 + cifs_sb->local_nls); 90 + if (!s) 91 + return -ENOMEM; 92 + convert_delimiter(s, '/'); 93 + cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, s); 94 + 95 + *path = s; 96 + return 0; 97 + } 98 + 99 + int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf) 27 100 { 28 101 int rc; 29 102 __le16 *smb2_path; 30 - struct smb2_file_all_info *smb2_data = NULL; 31 103 __u8 smb2_oplock; 104 + struct cifs_open_info_data *data = buf; 105 + struct smb2_file_all_info file_info = {}; 106 + struct smb2_file_all_info *smb2_data = data ? &file_info : NULL; 107 + struct kvec err_iov = {}; 108 + int err_buftype = CIFS_NO_BUFFER; 32 109 struct cifs_fid *fid = oparms->fid; 33 110 struct network_resiliency_req nr_ioctl_req; 34 111 35 112 smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); 36 - if (smb2_path == NULL) { 37 - rc = -ENOMEM; 38 - goto out; 39 - } 40 - 41 - smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 42 - GFP_KERNEL); 43 - if (smb2_data == NULL) { 44 - rc = -ENOMEM; 45 - goto out; 46 - } 113 + if (smb2_path == NULL) 114 + return -ENOMEM; 47 115 48 116 oparms->desired_access |= FILE_READ_ATTRIBUTES; 49 117 smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; 50 118 51 - rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, 52 - NULL, NULL); 119 + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, 120 + &err_buftype); 121 + if (rc && data) { 122 + struct smb2_hdr *hdr = err_iov.iov_base; 123 + 124 + if (unlikely(!err_iov.iov_base || err_buftype == CIFS_NO_BUFFER)) 125 + rc = -ENOMEM; 126 + else if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) { 127 + rc = smb2_parse_symlink_response(oparms->cifs_sb, &err_iov, 128 + &data->symlink_target); 129 + if (!rc) { 130 + memset(smb2_data, 0, sizeof(*smb2_data)); 131 + oparms->create_options |= OPEN_REPARSE_POINT; 132 + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, 133 + NULL, NULL, NULL); 134 + oparms->create_options &= ~OPEN_REPARSE_POINT; 135 + } 136 + } 137 + } 138 + 53 139 if (rc) 54 140 goto out; 55 - 56 141 57 142 if (oparms->tcon->use_resilient) { 58 143 /* default timeout is 0, servers pick default (120 seconds) */ ··· 158 73 rc = 0; 159 74 } 160 75 161 - if (buf) { 76 + if (smb2_data) { 162 77 /* if open response does not have IndexNumber field - get it */ 163 78 if (smb2_data->IndexNumber == 0) { 164 79 rc = SMB2_get_srv_num(xid, oparms->tcon, ··· 174 89 rc = 0; 175 90 } 176 91 } 177 - move_smb2_info_to_cifs(buf, smb2_data); 92 + memcpy(&data->fi, smb2_data, sizeof(data->fi)); 178 93 } 179 94 180 95 *oplock = smb2_oplock; 181 96 out: 182 - kfree(smb2_data); 97 + free_rsp_buf(err_buftype, err_iov.iov_base); 183 98 kfree(smb2_path); 184 99 return rc; 185 100 }
+88 -82
fs/cifs/smb2inode.c
··· 24 24 #include "smb2pdu.h" 25 25 #include "smb2proto.h" 26 26 #include "cached_dir.h" 27 + #include "smb2status.h" 27 28 28 29 static void 29 30 free_set_inf_compound(struct smb_rqst *rqst) ··· 51 50 /* 52 51 * note: If cfile is passed, the reference to it is dropped here. 53 52 * So make sure that you do not reuse cfile after return from this func. 53 + * 54 + * If passing @err_iov and @err_buftype, ensure to make them both large enough (>= 3) to hold all 55 + * error responses. Caller is also responsible for freeing them up. 54 56 */ 55 - static int 56 - smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 57 - struct cifs_sb_info *cifs_sb, const char *full_path, 58 - __u32 desired_access, __u32 create_disposition, 59 - __u32 create_options, umode_t mode, void *ptr, int command, 60 - struct cifsFileInfo *cfile) 57 + static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 58 + struct cifs_sb_info *cifs_sb, const char *full_path, 59 + __u32 desired_access, __u32 create_disposition, __u32 create_options, 60 + umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile, 61 + struct kvec *err_iov, int *err_buftype) 61 62 { 62 63 struct cop_vars *vars = NULL; 63 64 struct kvec *rsp_iov; ··· 73 70 int num_rqst = 0; 74 71 int resp_buftype[3]; 75 72 struct smb2_query_info_rsp *qi_rsp = NULL; 73 + struct cifs_open_info_data *idata; 76 74 int flags = 0; 77 75 __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0}; 78 76 unsigned int size[2]; ··· 389 385 390 386 switch (command) { 391 387 case SMB2_OP_QUERY_INFO: 388 + idata = ptr; 389 + if (rc == 0 && cfile && cfile->symlink_target) { 390 + idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); 391 + if (!idata->symlink_target) 392 + rc = -ENOMEM; 393 + } 392 394 if (rc == 0) { 393 395 qi_rsp = (struct smb2_query_info_rsp *) 394 396 rsp_iov[1].iov_base; 395 397 rc = smb2_validate_and_copy_iov( 396 398 le16_to_cpu(qi_rsp->OutputBufferOffset), 397 399 le32_to_cpu(qi_rsp->OutputBufferLength), 398 - &rsp_iov[1], sizeof(struct smb2_file_all_info), 399 - ptr); 400 + &rsp_iov[1], sizeof(idata->fi), (char *)&idata->fi); 400 401 } 401 402 if (rqst[1].rq_iov) 402 403 SMB2_query_info_free(&rqst[1]); ··· 415 406 tcon->tid); 416 407 break; 417 408 case SMB2_OP_POSIX_QUERY_INFO: 409 + idata = ptr; 410 + if (rc == 0 && cfile && cfile->symlink_target) { 411 + idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); 412 + if (!idata->symlink_target) 413 + rc = -ENOMEM; 414 + } 418 415 if (rc == 0) { 419 416 qi_rsp = (struct smb2_query_info_rsp *) 420 417 rsp_iov[1].iov_base; 421 418 rc = smb2_validate_and_copy_iov( 422 419 le16_to_cpu(qi_rsp->OutputBufferOffset), 423 420 le32_to_cpu(qi_rsp->OutputBufferLength), 424 - &rsp_iov[1], sizeof(struct smb311_posix_qinfo) /* add SIDs */, ptr); 421 + &rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */, 422 + (char *)&idata->posix_fi); 425 423 } 426 424 if (rqst[1].rq_iov) 427 425 SMB2_query_info_free(&rqst[1]); ··· 493 477 free_set_inf_compound(rqst); 494 478 break; 495 479 } 496 - free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 497 - free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 498 - free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); 480 + 481 + if (rc && err_iov && err_buftype) { 482 + memcpy(err_iov, rsp_iov, 3 * sizeof(*err_iov)); 483 + memcpy(err_buftype, resp_buftype, 3 * sizeof(*err_buftype)); 484 + } else { 485 + free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 486 + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 487 + free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); 488 + } 499 489 kfree(vars); 500 490 return rc; 501 491 } 502 492 503 - void 504 - move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src) 505 - { 506 - memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src); 507 - dst->CurrentByteOffset = src->CurrentByteOffset; 508 - dst->Mode = src->Mode; 509 - dst->AlignmentRequirement = src->AlignmentRequirement; 510 - dst->IndexNumber1 = 0; /* we don't use it */ 511 - } 512 - 513 - int 514 - smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 515 - struct cifs_sb_info *cifs_sb, const char *full_path, 516 - FILE_ALL_INFO *data, bool *adjust_tz, bool *reparse) 493 + int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 494 + struct cifs_sb_info *cifs_sb, const char *full_path, 495 + struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse) 517 496 { 518 497 int rc; 519 - struct smb2_file_all_info *smb2_data; 520 498 __u32 create_options = 0; 521 499 struct cifsFileInfo *cfile; 522 500 struct cached_fid *cfid = NULL; 501 + struct kvec err_iov[3] = {}; 502 + int err_buftype[3] = {}; 523 503 524 504 *adjust_tz = false; 525 505 *reparse = false; 526 - 527 - smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 528 - GFP_KERNEL); 529 - if (smb2_data == NULL) 530 - return -ENOMEM; 531 506 532 507 if (strcmp(full_path, "")) 533 508 rc = -ENOENT; ··· 527 520 /* If it is a root and its handle is cached then use it */ 528 521 if (!rc) { 529 522 if (cfid->file_all_info_is_valid) { 530 - move_smb2_info_to_cifs(data, 531 - &cfid->file_all_info); 523 + memcpy(&data->fi, &cfid->file_all_info, sizeof(data->fi)); 532 524 } else { 533 - rc = SMB2_query_info(xid, tcon, 534 - cfid->fid.persistent_fid, 535 - cfid->fid.volatile_fid, smb2_data); 536 - if (!rc) 537 - move_smb2_info_to_cifs(data, smb2_data); 525 + rc = SMB2_query_info(xid, tcon, cfid->fid.persistent_fid, 526 + cfid->fid.volatile_fid, &data->fi); 538 527 } 539 528 close_cached_dir(cfid); 540 - goto out; 529 + return rc; 541 530 } 542 531 543 532 cifs_get_readable_path(tcon, full_path, &cfile); 544 - rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 545 - FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, 546 - ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile); 533 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN, 534 + create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile, 535 + err_iov, err_buftype); 547 536 if (rc == -EOPNOTSUPP) { 537 + if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER && 538 + ((struct smb2_hdr *)err_iov[0].iov_base)->Command == SMB2_CREATE && 539 + ((struct smb2_hdr *)err_iov[0].iov_base)->Status == STATUS_STOPPED_ON_SYMLINK) { 540 + rc = smb2_parse_symlink_response(cifs_sb, err_iov, &data->symlink_target); 541 + if (rc) 542 + goto out; 543 + } 548 544 *reparse = true; 549 545 create_options |= OPEN_REPARSE_POINT; 550 546 551 547 /* Failed on a symbolic link - query a reparse point info */ 552 548 cifs_get_readable_path(tcon, full_path, &cfile); 553 - rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 554 - FILE_READ_ATTRIBUTES, FILE_OPEN, 555 - create_options, ACL_NO_MODE, 556 - smb2_data, SMB2_OP_QUERY_INFO, cfile); 549 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, 550 + FILE_OPEN, create_options, ACL_NO_MODE, data, 551 + SMB2_OP_QUERY_INFO, cfile, NULL, NULL); 557 552 } 558 - if (rc) 559 - goto out; 560 553 561 - move_smb2_info_to_cifs(data, smb2_data); 562 554 out: 563 - kfree(smb2_data); 555 + free_rsp_buf(err_buftype[0], err_iov[0].iov_base); 556 + free_rsp_buf(err_buftype[1], err_iov[1].iov_base); 557 + free_rsp_buf(err_buftype[2], err_iov[2].iov_base); 564 558 return rc; 565 559 } 566 560 567 561 568 - int 569 - smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 570 - struct cifs_sb_info *cifs_sb, const char *full_path, 571 - struct smb311_posix_qinfo *data, bool *adjust_tz, bool *reparse) 562 + int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 563 + struct cifs_sb_info *cifs_sb, const char *full_path, 564 + struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse) 572 565 { 573 566 int rc; 574 567 __u32 create_options = 0; 575 568 struct cifsFileInfo *cfile; 576 - struct smb311_posix_qinfo *smb2_data; 569 + struct kvec err_iov[3] = {}; 570 + int err_buftype[3] = {}; 577 571 578 572 *adjust_tz = false; 579 573 *reparse = false; 580 - 581 - /* BB TODO: Make struct larger when add support for parsing owner SIDs */ 582 - smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo), 583 - GFP_KERNEL); 584 - if (smb2_data == NULL) 585 - return -ENOMEM; 586 574 587 575 /* 588 576 * BB TODO: Add support for using the cached root handle. ··· 587 585 */ 588 586 589 587 cifs_get_readable_path(tcon, full_path, &cfile); 590 - rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 591 - FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, 592 - ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile); 588 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN, 589 + create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile, 590 + err_iov, err_buftype); 593 591 if (rc == -EOPNOTSUPP) { 594 592 /* BB TODO: When support for special files added to Samba re-verify this path */ 593 + if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER && 594 + ((struct smb2_hdr *)err_iov[0].iov_base)->Command == SMB2_CREATE && 595 + ((struct smb2_hdr *)err_iov[0].iov_base)->Status == STATUS_STOPPED_ON_SYMLINK) { 596 + rc = smb2_parse_symlink_response(cifs_sb, err_iov, &data->symlink_target); 597 + if (rc) 598 + goto out; 599 + } 595 600 *reparse = true; 596 601 create_options |= OPEN_REPARSE_POINT; 597 602 598 603 /* Failed on a symbolic link - query a reparse point info */ 599 604 cifs_get_readable_path(tcon, full_path, &cfile); 600 - rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 601 - FILE_READ_ATTRIBUTES, FILE_OPEN, 602 - create_options, ACL_NO_MODE, 603 - smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile); 605 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, 606 + FILE_OPEN, create_options, ACL_NO_MODE, data, 607 + SMB2_OP_POSIX_QUERY_INFO, cfile, NULL, NULL); 604 608 } 605 - if (rc) 606 - goto out; 607 - 608 - /* TODO: will need to allow for the 2 SIDs when add support for getting owner UID/GID */ 609 - memcpy(data, smb2_data, sizeof(struct smb311_posix_qinfo)); 610 609 611 610 out: 612 - kfree(smb2_data); 611 + free_rsp_buf(err_buftype[0], err_iov[0].iov_base); 612 + free_rsp_buf(err_buftype[1], err_iov[1].iov_base); 613 + free_rsp_buf(err_buftype[2], err_iov[2].iov_base); 613 614 return rc; 614 615 } 615 616 ··· 624 619 return smb2_compound_op(xid, tcon, cifs_sb, name, 625 620 FILE_WRITE_ATTRIBUTES, FILE_CREATE, 626 621 CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR, 627 - NULL); 622 + NULL, NULL, NULL); 628 623 } 629 624 630 625 void ··· 646 641 tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, 647 642 FILE_WRITE_ATTRIBUTES, FILE_CREATE, 648 643 CREATE_NOT_FILE, ACL_NO_MODE, 649 - &data, SMB2_OP_SET_INFO, cfile); 644 + &data, SMB2_OP_SET_INFO, cfile, NULL, NULL); 650 645 if (tmprc == 0) 651 646 cifs_i->cifsAttrs = dosattrs; 652 647 } ··· 657 652 { 658 653 return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 659 654 CREATE_NOT_FILE, ACL_NO_MODE, 660 - NULL, SMB2_OP_RMDIR, NULL); 655 + NULL, SMB2_OP_RMDIR, NULL, NULL, NULL); 661 656 } 662 657 663 658 int ··· 666 661 { 667 662 return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 668 663 CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, 669 - ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL); 664 + ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL); 670 665 } 671 666 672 667 static int ··· 685 680 } 686 681 rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access, 687 682 FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name, 688 - command, cfile); 683 + command, cfile, NULL, NULL); 689 684 smb2_rename_path: 690 685 kfree(smb2_to_name); 691 686 return rc; ··· 725 720 cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 726 721 return smb2_compound_op(xid, tcon, cifs_sb, full_path, 727 722 FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE, 728 - &eof, SMB2_OP_SET_EOF, cfile); 723 + &eof, SMB2_OP_SET_EOF, cfile, NULL, NULL); 729 724 } 730 725 731 726 int ··· 751 746 cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 752 747 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 753 748 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 754 - 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile); 749 + 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile, 750 + NULL, NULL); 755 751 cifs_put_tlink(tlink); 756 752 return rc; 757 753 }
+1 -1
fs/cifs/smb2misc.c
··· 248 248 * Some windows servers (win2016) will pad also the final 249 249 * PDU in a compound to 8 bytes. 250 250 */ 251 - if (((calc_len + 7) & ~7) == len) 251 + if (ALIGN(calc_len, 8) == len) 252 252 return 0; 253 253 254 254 /*
+54 -95
fs/cifs/smb2ops.c
··· 550 550 /* avoid spamming logs every 10 minutes, so log only in mount */ 551 551 if ((ses->chan_max > 1) && in_mount) 552 552 cifs_dbg(VFS, 553 - "empty network interface list returned by server %s\n", 553 + "multichannel not available\n" 554 + "Empty network interface list returned by server %s\n", 554 555 ses->server->hostname); 555 556 rc = -EINVAL; 556 557 goto out; ··· 801 800 802 801 rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid); 803 802 if (!rc) { 804 - if (cfid->is_valid) { 803 + if (cfid->has_lease) { 805 804 close_cached_dir(cfid); 806 805 return 0; 807 806 } ··· 831 830 return rc; 832 831 } 833 832 834 - static int 835 - smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, 836 - struct cifs_sb_info *cifs_sb, const char *full_path, 837 - u64 *uniqueid, FILE_ALL_INFO *data) 833 + static int smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, 834 + struct cifs_sb_info *cifs_sb, const char *full_path, 835 + u64 *uniqueid, struct cifs_open_info_data *data) 838 836 { 839 - *uniqueid = le64_to_cpu(data->IndexNumber); 837 + *uniqueid = le64_to_cpu(data->fi.IndexNumber); 840 838 return 0; 841 839 } 842 840 843 - static int 844 - smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, 845 - struct cifs_fid *fid, FILE_ALL_INFO *data) 841 + static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, 842 + struct cifsFileInfo *cfile, struct cifs_open_info_data *data) 846 843 { 847 - int rc; 848 - struct smb2_file_all_info *smb2_data; 844 + struct cifs_fid *fid = &cfile->fid; 849 845 850 - smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 851 - GFP_KERNEL); 852 - if (smb2_data == NULL) 853 - return -ENOMEM; 854 - 855 - rc = SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, 856 - smb2_data); 857 - if (!rc) 858 - move_smb2_info_to_cifs(data, smb2_data); 859 - kfree(smb2_data); 860 - return rc; 846 + if (cfile->symlink_target) { 847 + data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); 848 + if (!data->symlink_target) 849 + return -ENOMEM; 850 + } 851 + return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi); 861 852 } 862 853 863 854 #ifdef CONFIG_CIFS_XATTR ··· 2018 2025 2019 2026 static int 2020 2027 smb3_notify(const unsigned int xid, struct file *pfile, 2021 - void __user *ioc_buf) 2028 + void __user *ioc_buf, bool return_changes) 2022 2029 { 2023 - struct smb3_notify notify; 2030 + struct smb3_notify_info notify; 2031 + struct smb3_notify_info __user *pnotify_buf; 2024 2032 struct dentry *dentry = pfile->f_path.dentry; 2025 2033 struct inode *inode = file_inode(pfile); 2026 2034 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); ··· 2029 2035 struct cifs_fid fid; 2030 2036 struct cifs_tcon *tcon; 2031 2037 const unsigned char *path; 2038 + char *returned_ioctl_info = NULL; 2032 2039 void *page = alloc_dentry_path(); 2033 2040 __le16 *utf16_path = NULL; 2034 2041 u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 2035 2042 int rc = 0; 2043 + __u32 ret_len = 0; 2036 2044 2037 2045 path = build_path_from_dentry(dentry, page); 2038 2046 if (IS_ERR(path)) { ··· 2048 2052 goto notify_exit; 2049 2053 } 2050 2054 2051 - if (copy_from_user(&notify, ioc_buf, sizeof(struct smb3_notify))) { 2052 - rc = -EFAULT; 2053 - goto notify_exit; 2055 + if (return_changes) { 2056 + if (copy_from_user(&notify, ioc_buf, sizeof(struct smb3_notify_info))) { 2057 + rc = -EFAULT; 2058 + goto notify_exit; 2059 + } 2060 + } else { 2061 + if (copy_from_user(&notify, ioc_buf, sizeof(struct smb3_notify))) { 2062 + rc = -EFAULT; 2063 + goto notify_exit; 2064 + } 2065 + notify.data_len = 0; 2054 2066 } 2055 2067 2056 2068 tcon = cifs_sb_master_tcon(cifs_sb); ··· 2075 2071 goto notify_exit; 2076 2072 2077 2073 rc = SMB2_change_notify(xid, tcon, fid.persistent_fid, fid.volatile_fid, 2078 - notify.watch_tree, notify.completion_filter); 2074 + notify.watch_tree, notify.completion_filter, 2075 + notify.data_len, &returned_ioctl_info, &ret_len); 2079 2076 2080 2077 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 2081 2078 2082 2079 cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc); 2083 - 2080 + if (return_changes && (ret_len > 0) && (notify.data_len > 0)) { 2081 + if (ret_len > notify.data_len) 2082 + ret_len = notify.data_len; 2083 + pnotify_buf = (struct smb3_notify_info __user *)ioc_buf; 2084 + if (copy_to_user(pnotify_buf->notify_data, returned_ioctl_info, ret_len)) 2085 + rc = -EFAULT; 2086 + else if (copy_to_user(&pnotify_buf->data_len, &ret_len, sizeof(ret_len))) 2087 + rc = -EFAULT; 2088 + } 2089 + kfree(returned_ioctl_info); 2084 2090 notify_exit: 2085 2091 free_dentry_path(page); 2086 2092 kfree(utf16_path); ··· 2841 2827 } 2842 2828 } 2843 2829 2844 - #define SMB2_SYMLINK_STRUCT_SIZE \ 2845 - (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp)) 2846 - 2847 2830 static int 2848 2831 smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, 2849 2832 struct cifs_sb_info *cifs_sb, const char *full_path, ··· 2852 2841 struct cifs_open_parms oparms; 2853 2842 struct cifs_fid fid; 2854 2843 struct kvec err_iov = {NULL, 0}; 2855 - struct smb2_err_rsp *err_buf = NULL; 2856 - struct smb2_symlink_err_rsp *symlink; 2857 2844 struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); 2858 - unsigned int sub_len; 2859 - unsigned int sub_offset; 2860 - unsigned int print_len; 2861 - unsigned int print_offset; 2862 2845 int flags = CIFS_CP_CREATE_CLOSE_OP; 2863 2846 struct smb_rqst rqst[3]; 2864 2847 int resp_buftype[3]; ··· 2969 2964 goto querty_exit; 2970 2965 } 2971 2966 2972 - err_buf = err_iov.iov_base; 2973 - if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || 2974 - err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) { 2975 - rc = -EINVAL; 2976 - goto querty_exit; 2977 - } 2978 - 2979 - symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData; 2980 - if (le32_to_cpu(symlink->SymLinkErrorTag) != SYMLINK_ERROR_TAG || 2981 - le32_to_cpu(symlink->ReparseTag) != IO_REPARSE_TAG_SYMLINK) { 2982 - rc = -EINVAL; 2983 - goto querty_exit; 2984 - } 2985 - 2986 - /* open must fail on symlink - reset rc */ 2987 - rc = 0; 2988 - sub_len = le16_to_cpu(symlink->SubstituteNameLength); 2989 - sub_offset = le16_to_cpu(symlink->SubstituteNameOffset); 2990 - print_len = le16_to_cpu(symlink->PrintNameLength); 2991 - print_offset = le16_to_cpu(symlink->PrintNameOffset); 2992 - 2993 - if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { 2994 - rc = -EINVAL; 2995 - goto querty_exit; 2996 - } 2997 - 2998 - if (err_iov.iov_len < 2999 - SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { 3000 - rc = -EINVAL; 3001 - goto querty_exit; 3002 - } 3003 - 3004 - *target_path = cifs_strndup_from_utf16( 3005 - (char *)symlink->PathBuffer + sub_offset, 3006 - sub_len, true, cifs_sb->local_nls); 3007 - if (!(*target_path)) { 3008 - rc = -ENOMEM; 3009 - goto querty_exit; 3010 - } 3011 - convert_delimiter(*target_path, '/'); 3012 - cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); 2967 + rc = smb2_parse_symlink_response(cifs_sb, &err_iov, target_path); 3013 2968 3014 2969 querty_exit: 3015 2970 cifs_dbg(FYI, "query symlink rc %d\n", rc); ··· 5079 5114 { 5080 5115 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 5081 5116 int rc = -EPERM; 5082 - FILE_ALL_INFO *buf = NULL; 5117 + struct cifs_open_info_data buf = {}; 5083 5118 struct cifs_io_parms io_parms = {0}; 5084 5119 __u32 oplock = 0; 5085 5120 struct cifs_fid fid; ··· 5095 5130 * and was used by default in earlier versions of Windows 5096 5131 */ 5097 5132 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) 5098 - goto out; 5133 + return rc; 5099 5134 5100 5135 /* 5101 5136 * TODO: Add ability to create instead via reparse point. Windows (e.g. ··· 5104 5139 */ 5105 5140 5106 5141 if (!S_ISCHR(mode) && !S_ISBLK(mode)) 5107 - goto out; 5142 + return rc; 5108 5143 5109 5144 cifs_dbg(FYI, "sfu compat create special file\n"); 5110 - 5111 - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 5112 - if (buf == NULL) { 5113 - rc = -ENOMEM; 5114 - goto out; 5115 - } 5116 5145 5117 5146 oparms.tcon = tcon; 5118 5147 oparms.cifs_sb = cifs_sb; ··· 5122 5163 oplock = REQ_OPLOCK; 5123 5164 else 5124 5165 oplock = 0; 5125 - rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf); 5166 + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf); 5126 5167 if (rc) 5127 - goto out; 5168 + return rc; 5128 5169 5129 5170 /* 5130 5171 * BB Do not bother to decode buf since no local inode yet to put 5131 5172 * timestamps in, but we can reuse it safely. 5132 5173 */ 5133 5174 5134 - pdev = (struct win_dev *)buf; 5175 + pdev = (struct win_dev *)&buf.fi; 5135 5176 io_parms.pid = current->tgid; 5136 5177 io_parms.tcon = tcon; 5137 5178 io_parms.offset = 0; 5138 5179 io_parms.length = sizeof(struct win_dev); 5139 - iov[1].iov_base = buf; 5180 + iov[1].iov_base = &buf.fi; 5140 5181 iov[1].iov_len = sizeof(struct win_dev); 5141 5182 if (S_ISCHR(mode)) { 5142 5183 memcpy(pdev->type, "IntxCHR", 8); ··· 5155 5196 d_drop(dentry); 5156 5197 5157 5198 /* FIXME: add code here to set EAs */ 5158 - out: 5159 - kfree(buf); 5199 + 5200 + cifs_free_open_info(&buf); 5160 5201 return rc; 5161 5202 } 5162 5203
+47 -28
fs/cifs/smb2pdu.c
··· 466 466 /* 467 467 * Context Data length must be rounded to multiple of 8 for some servers 468 468 */ 469 - pneg_ctxt->DataLength = cpu_to_le16(DIV_ROUND_UP( 470 - sizeof(struct smb2_signing_capabilities) - 471 - sizeof(struct smb2_neg_context) + 472 - (num_algs * 2 /* sizeof u16 */), 8) * 8); 469 + pneg_ctxt->DataLength = cpu_to_le16(ALIGN(sizeof(struct smb2_signing_capabilities) - 470 + sizeof(struct smb2_neg_context) + 471 + (num_algs * sizeof(u16)), 8)); 473 472 pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(num_algs); 474 473 pneg_ctxt->SigningAlgorithms[0] = cpu_to_le16(SIGNING_ALG_AES_CMAC); 475 474 476 - ctxt_len += 2 /* sizeof le16 */ * num_algs; 477 - ctxt_len = DIV_ROUND_UP(ctxt_len, 8) * 8; 475 + ctxt_len += sizeof(__le16) * num_algs; 476 + ctxt_len = ALIGN(ctxt_len, 8); 478 477 return ctxt_len; 479 478 /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */ 480 479 } ··· 510 511 /* copy up to max of first 100 bytes of server name to NetName field */ 511 512 pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp)); 512 513 /* context size is DataLength + minimal smb2_neg_context */ 513 - return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) + 514 - sizeof(struct smb2_neg_context), 8) * 8; 514 + return ALIGN(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg_context), 8); 515 515 } 516 516 517 517 static void ··· 555 557 * round up total_len of fixed part of SMB3 negotiate request to 8 556 558 * byte boundary before adding negotiate contexts 557 559 */ 558 - *total_len = roundup(*total_len, 8); 560 + *total_len = ALIGN(*total_len, 8); 559 561 560 562 pneg_ctxt = (*total_len) + (char *)req; 561 563 req->NegotiateContextOffset = cpu_to_le32(*total_len); 562 564 563 565 build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); 564 - ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8; 566 + ctxt_len = ALIGN(sizeof(struct smb2_preauth_neg_context), 8); 565 567 *total_len += ctxt_len; 566 568 pneg_ctxt += ctxt_len; 567 569 568 570 build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); 569 - ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_encryption_neg_context), 8) * 8; 571 + ctxt_len = ALIGN(sizeof(struct smb2_encryption_neg_context), 8); 570 572 *total_len += ctxt_len; 571 573 pneg_ctxt += ctxt_len; 572 574 ··· 593 595 if (server->compress_algorithm) { 594 596 build_compression_ctxt((struct smb2_compression_capabilities_context *) 595 597 pneg_ctxt); 596 - ctxt_len = DIV_ROUND_UP( 597 - sizeof(struct smb2_compression_capabilities_context), 598 - 8) * 8; 598 + ctxt_len = ALIGN(sizeof(struct smb2_compression_capabilities_context), 8); 599 599 *total_len += ctxt_len; 600 600 pneg_ctxt += ctxt_len; 601 601 neg_context_count++; ··· 776 780 if (rc) 777 781 break; 778 782 /* offsets must be 8 byte aligned */ 779 - clen = (clen + 7) & ~0x7; 783 + clen = ALIGN(clen, 8); 780 784 offset += clen + sizeof(struct smb2_neg_context); 781 785 len_of_ctxts -= clen; 782 786 } ··· 2420 2424 unsigned int acelen, acl_size, ace_count; 2421 2425 unsigned int owner_offset = 0; 2422 2426 unsigned int group_offset = 0; 2423 - struct smb3_acl acl; 2427 + struct smb3_acl acl = {}; 2424 2428 2425 - *len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8); 2429 + *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8); 2426 2430 2427 2431 if (set_owner) { 2428 2432 /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */ ··· 2493 2497 acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */ 2494 2498 acl.AclSize = cpu_to_le16(acl_size); 2495 2499 acl.AceCount = cpu_to_le16(ace_count); 2500 + /* acl.Sbz1 and Sbz2 MBZ so are not set here, but initialized above */ 2496 2501 memcpy(aclptr, &acl, sizeof(struct smb3_acl)); 2497 2502 2498 2503 buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd); 2499 - *len = roundup(ptr - (__u8 *)buf, 8); 2504 + *len = round_up((unsigned int)(ptr - (__u8 *)buf), 8); 2500 2505 2501 2506 return buf; 2502 2507 } ··· 2591 2594 * final path needs to be 8-byte aligned as specified in 2592 2595 * MS-SMB2 2.2.13 SMB2 CREATE Request. 2593 2596 */ 2594 - *out_size = roundup(*out_len * sizeof(__le16), 8); 2597 + *out_size = round_up(*out_len * sizeof(__le16), 8); 2595 2598 *out_path = kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL); 2596 2599 if (!*out_path) 2597 2600 return -ENOMEM; ··· 2836 2839 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; 2837 2840 /* MUST set path len (NameLength) to 0 opening root of share */ 2838 2841 req->NameLength = cpu_to_le16(uni_path_len - 2); 2839 - copy_size = uni_path_len; 2840 - if (copy_size % 8 != 0) 2841 - copy_size = roundup(copy_size, 8); 2842 + copy_size = round_up(uni_path_len, 8); 2842 2843 copy_path = kzalloc(copy_size, GFP_KERNEL); 2843 2844 if (!copy_path) 2844 2845 return -ENOMEM; ··· 3480 3485 if (rc) 3481 3486 return rc; 3482 3487 3483 - memcpy(data, begin_of_buf, buffer_length); 3488 + memcpy(data, begin_of_buf, minbufsize); 3484 3489 3485 3490 return 0; 3486 3491 } ··· 3604 3609 3605 3610 rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset), 3606 3611 le32_to_cpu(rsp->OutputBufferLength), 3607 - &rsp_iov, min_len, *data); 3612 + &rsp_iov, dlen ? *dlen : min_len, *data); 3608 3613 if (rc && allocated) { 3609 3614 kfree(*data); 3610 3615 *data = NULL; ··· 3710 3715 int 3711 3716 SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, 3712 3717 u64 persistent_fid, u64 volatile_fid, bool watch_tree, 3713 - u32 completion_filter) 3718 + u32 completion_filter, u32 max_out_data_len, char **out_data, 3719 + u32 *plen /* returned data len */) 3714 3720 { 3715 3721 struct cifs_ses *ses = tcon->ses; 3716 3722 struct TCP_Server_Info *server = cifs_pick_channel(ses); 3717 3723 struct smb_rqst rqst; 3724 + struct smb2_change_notify_rsp *smb_rsp; 3718 3725 struct kvec iov[1]; 3719 3726 struct kvec rsp_iov = {NULL, 0}; 3720 3727 int resp_buftype = CIFS_NO_BUFFER; ··· 3732 3735 3733 3736 memset(&rqst, 0, sizeof(struct smb_rqst)); 3734 3737 memset(&iov, 0, sizeof(iov)); 3738 + if (plen) 3739 + *plen = 0; 3740 + 3735 3741 rqst.rq_iov = iov; 3736 3742 rqst.rq_nvec = 1; 3737 3743 ··· 3753 3753 cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE); 3754 3754 trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid, 3755 3755 (u8)watch_tree, completion_filter, rc); 3756 - } else 3756 + } else { 3757 3757 trace_smb3_notify_done(xid, persistent_fid, tcon->tid, 3758 - ses->Suid, (u8)watch_tree, completion_filter); 3758 + ses->Suid, (u8)watch_tree, completion_filter); 3759 + /* validate that notify information is plausible */ 3760 + if ((rsp_iov.iov_base == NULL) || 3761 + (rsp_iov.iov_len < sizeof(struct smb2_change_notify_rsp))) 3762 + goto cnotify_exit; 3763 + 3764 + smb_rsp = (struct smb2_change_notify_rsp *)rsp_iov.iov_base; 3765 + 3766 + smb2_validate_iov(le16_to_cpu(smb_rsp->OutputBufferOffset), 3767 + le32_to_cpu(smb_rsp->OutputBufferLength), &rsp_iov, 3768 + sizeof(struct file_notify_information)); 3769 + 3770 + *out_data = kmemdup((char *)smb_rsp + le16_to_cpu(smb_rsp->OutputBufferOffset), 3771 + le32_to_cpu(smb_rsp->OutputBufferLength), GFP_KERNEL); 3772 + if (*out_data == NULL) { 3773 + rc = -ENOMEM; 3774 + goto cnotify_exit; 3775 + } else 3776 + *plen = le32_to_cpu(smb_rsp->OutputBufferLength); 3777 + } 3759 3778 3760 3779 cnotify_exit: 3761 3780 if (rqst.rq_iov) ··· 4122 4103 if (request_type & CHAINED_REQUEST) { 4123 4104 if (!(request_type & END_OF_CHAIN)) { 4124 4105 /* next 8-byte aligned request */ 4125 - *total_len = DIV_ROUND_UP(*total_len, 8) * 8; 4106 + *total_len = ALIGN(*total_len, 8); 4126 4107 shdr->NextCommand = cpu_to_le32(*total_len); 4127 4108 } else /* END_OF_CHAIN */ 4128 4109 shdr->NextCommand = 0;
+3
fs/cifs/smb2pdu.h
··· 56 56 57 57 #define COMPOUND_FID 0xFFFFFFFFFFFFFFFFULL 58 58 59 + #define SMB2_SYMLINK_STRUCT_SIZE \ 60 + (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp)) 61 + 59 62 #define SYMLINK_ERROR_TAG 0x4c4d5953 60 63 61 64 struct smb2_symlink_err_rsp {
+11 -14
fs/cifs/smb2proto.h
··· 53 53 struct TCP_Server_Info *srv); 54 54 extern int smb3_handle_read_data(struct TCP_Server_Info *server, 55 55 struct mid_q_entry *mid); 56 - 57 - extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, 58 - struct smb2_file_all_info *src); 59 56 extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, 60 57 struct cifs_sb_info *cifs_sb, const char *path, 61 58 __u32 *reparse_tag); 62 - extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 63 - struct cifs_sb_info *cifs_sb, 64 - const char *full_path, FILE_ALL_INFO *data, 65 - bool *adjust_tz, bool *symlink); 59 + int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 60 + struct cifs_sb_info *cifs_sb, const char *full_path, 61 + struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse); 66 62 extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, 67 63 const char *full_path, __u64 size, 68 64 struct cifs_sb_info *cifs_sb, bool set_alloc); ··· 91 95 struct cifs_sb_info *cifs_sb, 92 96 const unsigned char *path, char *pbuf, 93 97 unsigned int *pbytes_read); 94 - extern int smb2_open_file(const unsigned int xid, 95 - struct cifs_open_parms *oparms, 96 - __u32 *oplock, FILE_ALL_INFO *buf); 98 + int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path); 99 + int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, 100 + void *buf); 97 101 extern int smb2_unlock_range(struct cifsFileInfo *cfile, 98 102 struct file_lock *flock, const unsigned int xid); 99 103 extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); ··· 144 148 extern void SMB2_ioctl_free(struct smb_rqst *rqst); 145 149 extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, 146 150 u64 persistent_fid, u64 volatile_fid, bool watch_tree, 147 - u32 completion_filter); 151 + u32 completion_filter, u32 max_out_data_len, 152 + char **out_data, u32 *plen /* returned data len */); 148 153 149 154 extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 150 155 u64 persistent_fid, u64 volatile_fid, ··· 275 278 struct kvec *rsp, int *buftype, 276 279 struct cifs_sb_info *cifs_sb); 277 280 /* query path info from the server using SMB311 POSIX extensions*/ 278 - extern int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 279 - struct cifs_sb_info *sb, const char *path, struct smb311_posix_qinfo *qinf, 280 - bool *adjust_tx, bool *symlink); 281 + int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 282 + struct cifs_sb_info *cifs_sb, const char *full_path, 283 + struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse); 281 284 int posix_info_parse(const void *beg, const void *end, 282 285 struct smb2_posix_info_parsed *out); 283 286 int posix_info_sid_size(const void *beg, const void *end);