1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    VFS initialisation and support functions
5    Copyright (C) Tim Potter 1999
6    Copyright (C) Alexander Bokovoy 2002
7    Copyright (C) James Peach 2006
8    Copyright (C) Volker Lendecke 2009
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 
23    This work was sponsored by Optifacio Software Services, Inc.
24 */
25 
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "../lib/util/memcache.h"
31 #include "transfer_file.h"
32 #include "ntioctl.h"
33 #include "lib/util/tevent_unix.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
36 
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
39 
40 static_decl_vfs;
41 
42 struct vfs_fsp_data {
43     struct vfs_fsp_data *next;
44     struct vfs_handle_struct *owner;
45     void (*destroy)(void *p_data);
46     void *_dummy_;
47     /* NOTE: This structure contains four pointers so that we can guarantee
48      * that the end of the structure is always both 4-byte and 8-byte aligned.
49      */
50 };
51 
52 struct vfs_init_function_entry {
53 	char *name;
54 	struct vfs_init_function_entry *prev, *next;
55 	const struct vfs_fn_pointers *fns;
56 };
57 
58 /****************************************************************************
59     maintain the list of available backends
60 ****************************************************************************/
61 
vfs_find_backend_entry(const char * name)62 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
63 {
64 	struct vfs_init_function_entry *entry = backends;
65 
66 	DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
67 
68 	while(entry) {
69 		if (strcmp(entry->name, name)==0) return entry;
70 		entry = entry->next;
71 	}
72 
73 	return NULL;
74 }
75 
smb_register_vfs(int version,const char * name,const struct vfs_fn_pointers * fns)76 NTSTATUS smb_register_vfs(int version, const char *name,
77 			  const struct vfs_fn_pointers *fns)
78 {
79 	struct vfs_init_function_entry *entry = backends;
80 
81  	if ((version != SMB_VFS_INTERFACE_VERSION)) {
82 		DEBUG(0, ("Failed to register vfs module.\n"
83 		          "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
84 		          "current SMB_VFS_INTERFACE_VERSION is %d.\n"
85 		          "Please recompile against the current Samba Version!\n",
86 			  version, SMB_VFS_INTERFACE_VERSION));
87 		return NT_STATUS_OBJECT_TYPE_MISMATCH;
88   	}
89 
90 	if (!name || !name[0]) {
91 		DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
92 		return NT_STATUS_INVALID_PARAMETER;
93 	}
94 
95 	if (vfs_find_backend_entry(name)) {
96 		DEBUG(0,("VFS module %s already loaded!\n", name));
97 		return NT_STATUS_OBJECT_NAME_COLLISION;
98 	}
99 
100 	entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
101 	entry->name = smb_xstrdup(name);
102 	entry->fns = fns;
103 
104 	DLIST_ADD(backends, entry);
105 	DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
106 	return NT_STATUS_OK;
107 }
108 
109 /****************************************************************************
110   initialise default vfs hooks
111 ****************************************************************************/
112 
vfs_init_default(connection_struct * conn)113 static void vfs_init_default(connection_struct *conn)
114 {
115 	DEBUG(3, ("Initialising default vfs hooks\n"));
116 	vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
117 }
118 
119 /****************************************************************************
120   initialise custom vfs hooks
121  ****************************************************************************/
122 
vfs_init_custom(connection_struct * conn,const char * vfs_object)123 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
124 {
125 	char *module_path = NULL;
126 	char *module_name = NULL;
127 	char *module_param = NULL, *p;
128 	vfs_handle_struct *handle;
129 	const struct vfs_init_function_entry *entry;
130 
131 	if (!conn||!vfs_object||!vfs_object[0]) {
132 		DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
133 			  "empty vfs_object!\n"));
134 		return False;
135 	}
136 
137 	if(!backends) {
138 		static_init_vfs(NULL);
139 	}
140 
141 	DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
142 
143 	module_path = smb_xstrdup(vfs_object);
144 
145 	p = strchr_m(module_path, ':');
146 
147 	if (p) {
148 		*p = 0;
149 		module_param = p+1;
150 		trim_char(module_param, ' ', ' ');
151 	}
152 
153 	trim_char(module_path, ' ', ' ');
154 
155 	module_name = smb_xstrdup(module_path);
156 
157 	if ((module_name[0] == '/') &&
158 	    (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
159 
160 		/*
161 		 * Extract the module name from the path. Just use the base
162 		 * name of the last path component.
163 		 */
164 
165 		SAFE_FREE(module_name);
166 		module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
167 
168 		p = strchr_m(module_name, '.');
169 
170 		if (p != NULL) {
171 			*p = '\0';
172 		}
173 	}
174 
175 	/* First, try to load the module with the new module system */
176 	entry = vfs_find_backend_entry(module_name);
177 	if (!entry) {
178 		NTSTATUS status;
179 
180 		DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
181 			  vfs_object));
182 
183 		status = smb_load_module("vfs", module_path);
184 		if (!NT_STATUS_IS_OK(status)) {
185 			DEBUG(0, ("error probing vfs module '%s': %s\n",
186 				  module_path, nt_errstr(status)));
187 			goto fail;
188 		}
189 
190 		entry = vfs_find_backend_entry(module_name);
191 		if (!entry) {
192 			DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
193 			goto fail;
194 		}
195 	}
196 
197 	DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
198 
199 	handle = talloc_zero(conn, vfs_handle_struct);
200 	if (!handle) {
201 		DEBUG(0,("TALLOC_ZERO() failed!\n"));
202 		goto fail;
203 	}
204 	handle->conn = conn;
205 	handle->fns = entry->fns;
206 	if (module_param) {
207 		handle->param = talloc_strdup(conn, module_param);
208 	}
209 	DLIST_ADD(conn->vfs_handles, handle);
210 
211 	SAFE_FREE(module_path);
212 	SAFE_FREE(module_name);
213 	return True;
214 
215  fail:
216 	SAFE_FREE(module_path);
217 	SAFE_FREE(module_name);
218 	return False;
219 }
220 
221 /*****************************************************************
222  Allow VFS modules to extend files_struct with VFS-specific state.
223  This will be ok for small numbers of extensions, but might need to
224  be refactored if it becomes more widely used.
225 ******************************************************************/
226 
227 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
228 
vfs_add_fsp_extension_notype(vfs_handle_struct * handle,files_struct * fsp,size_t ext_size,void (* destroy_fn)(void * p_data))229 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
230 				   files_struct *fsp, size_t ext_size,
231 				   void (*destroy_fn)(void *p_data))
232 {
233 	struct vfs_fsp_data *ext;
234 	void * ext_data;
235 
236 	/* Prevent VFS modules adding multiple extensions. */
237 	if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
238 		return ext_data;
239 	}
240 
241 	ext = (struct vfs_fsp_data *)TALLOC_ZERO(
242 		handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
243 	if (ext == NULL) {
244 		return NULL;
245 	}
246 
247 	ext->owner = handle;
248 	ext->next = fsp->vfs_extension;
249 	ext->destroy = destroy_fn;
250 	fsp->vfs_extension = ext;
251 	return EXT_DATA_AREA(ext);
252 }
253 
vfs_remove_fsp_extension(vfs_handle_struct * handle,files_struct * fsp)254 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
255 {
256 	struct vfs_fsp_data *curr;
257 	struct vfs_fsp_data *prev;
258 
259 	for (curr = fsp->vfs_extension, prev = NULL;
260 	     curr;
261 	     prev = curr, curr = curr->next) {
262 		if (curr->owner == handle) {
263 		    if (prev) {
264 			    prev->next = curr->next;
265 		    } else {
266 			    fsp->vfs_extension = curr->next;
267 		    }
268 		    if (curr->destroy) {
269 			    curr->destroy(EXT_DATA_AREA(curr));
270 		    }
271 		    TALLOC_FREE(curr);
272 		    return;
273 		}
274 	}
275 }
276 
vfs_remove_all_fsp_extensions(files_struct * fsp)277 void vfs_remove_all_fsp_extensions(files_struct *fsp)
278 {
279 	struct vfs_fsp_data *curr;
280 	struct vfs_fsp_data *next;
281 
282 	for (curr = fsp->vfs_extension; curr; curr = next) {
283 
284 		next = curr->next;
285 		fsp->vfs_extension = next;
286 
287 		if (curr->destroy) {
288 			curr->destroy(EXT_DATA_AREA(curr));
289 		}
290 		TALLOC_FREE(curr);
291 	}
292 }
293 
vfs_memctx_fsp_extension(vfs_handle_struct * handle,files_struct * fsp)294 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
295 {
296 	struct vfs_fsp_data *head;
297 
298 	for (head = fsp->vfs_extension; head; head = head->next) {
299 		if (head->owner == handle) {
300 			return head;
301 		}
302 	}
303 
304 	return NULL;
305 }
306 
vfs_fetch_fsp_extension(vfs_handle_struct * handle,files_struct * fsp)307 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
308 {
309 	struct vfs_fsp_data *head;
310 
311 	head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
312 	if (head != NULL) {
313 		return EXT_DATA_AREA(head);
314 	}
315 
316 	return NULL;
317 }
318 
319 #undef EXT_DATA_AREA
320 
321 /*
322  * Ensure this module catches all VFS functions.
323  */
324 #ifdef DEVELOPER
smb_vfs_assert_all_fns(const struct vfs_fn_pointers * fns,const char * module)325 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
326 			    const char *module)
327 {
328 	bool missing_fn = false;
329 	unsigned int idx;
330 	const uintptr_t *end = (const uintptr_t *)(fns + 1);
331 
332 	for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
333 		if (*((const uintptr_t *)fns + idx) == 0) {
334 			DBG_ERR("VFS function at index %d not implemented "
335 				"in module %s\n", idx, module);
336 			missing_fn = true;
337 		}
338 	}
339 
340 	if (missing_fn) {
341 		smb_panic("Required VFS function not implemented in module.\n");
342 	}
343 }
344 #else
smb_vfs_assert_all_fns(const struct vfs_fn_pointers * fns,const char * module)345 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
346 			    const char *module)
347 {
348 }
349 #endif
350 
351 /*****************************************************************
352  Generic VFS init.
353 ******************************************************************/
354 
smbd_vfs_init(connection_struct * conn)355 bool smbd_vfs_init(connection_struct *conn)
356 {
357 	const char **vfs_objects;
358 	unsigned int i = 0;
359 	int j = 0;
360 
361 	/* Normal share - initialise with disk access functions */
362 	vfs_init_default(conn);
363 
364 	/* No need to load vfs modules for printer connections */
365 	if (conn->printer) {
366 		return True;
367 	}
368 
369 	vfs_objects = lp_vfs_objects(SNUM(conn));
370 
371 	/* Override VFS functions if 'vfs object' was not specified*/
372 	if (!vfs_objects || !vfs_objects[0])
373 		return True;
374 
375 	for (i=0; vfs_objects[i] ;) {
376 		i++;
377 	}
378 
379 	for (j=i-1; j >= 0; j--) {
380 		if (!vfs_init_custom(conn, vfs_objects[j])) {
381 			DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
382 			return False;
383 		}
384 	}
385 	return True;
386 }
387 
388 /*******************************************************************
389  Check if a file exists in the vfs.
390 ********************************************************************/
391 
vfs_file_exist(connection_struct * conn,struct smb_filename * smb_fname)392 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
393 {
394 	/* Only return OK if stat was successful and S_ISREG */
395 	if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
396 	    S_ISREG(smb_fname->st.st_ex_mode)) {
397 		return NT_STATUS_OK;
398 	}
399 
400 	return NT_STATUS_OBJECT_NAME_NOT_FOUND;
401 }
402 
vfs_valid_pread_range(off_t offset,size_t length)403 bool vfs_valid_pread_range(off_t offset, size_t length)
404 {
405 	return sys_valid_io_range(offset, length);
406 }
407 
vfs_valid_pwrite_range(off_t offset,size_t length)408 bool vfs_valid_pwrite_range(off_t offset, size_t length)
409 {
410 	/*
411 	 * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write
412 	 */
413 	static const uint64_t maxfilesize = 0xfffffff0000;
414 	uint64_t last_byte_ofs;
415 	bool ok;
416 
417 	ok = sys_valid_io_range(offset, length);
418 	if (!ok) {
419 		return false;
420 	}
421 
422 	if (length == 0) {
423 		return true;
424 	}
425 
426 	last_byte_ofs = offset + length;
427 	if (last_byte_ofs > maxfilesize) {
428 		return false;
429 	}
430 
431 	return true;
432 }
433 
vfs_pwrite_data(struct smb_request * req,files_struct * fsp,const char * buffer,size_t N,off_t offset)434 ssize_t vfs_pwrite_data(struct smb_request *req,
435 			files_struct *fsp,
436 			const char *buffer,
437 			size_t N,
438 			off_t offset)
439 {
440 	size_t total=0;
441 	ssize_t ret;
442 	bool ok;
443 
444 	ok = vfs_valid_pwrite_range(offset, N);
445 	if (!ok) {
446 		errno = EINVAL;
447 		return -1;
448 	}
449 
450 	if (req && req->unread_bytes) {
451 		int sockfd = req->xconn->transport.sock;
452 		SMB_ASSERT(req->unread_bytes == N);
453 		/* VFS_RECVFILE must drain the socket
454 		 * before returning. */
455 		req->unread_bytes = 0;
456 		/*
457 		 * Leave the socket non-blocking and
458 		 * use SMB_VFS_RECVFILE. If it returns
459 		 * EAGAIN || EWOULDBLOCK temporarily set
460 		 * the socket blocking and retry
461 		 * the RECVFILE.
462 		 */
463 		while (total < N) {
464 			ret = SMB_VFS_RECVFILE(sockfd,
465 						fsp,
466 						offset + total,
467 						N - total);
468 			if (ret == 0 || (ret == -1 &&
469 					 (errno == EAGAIN ||
470 					  errno == EWOULDBLOCK))) {
471 				int old_flags;
472 				/* Ensure the socket is blocking. */
473 				old_flags = fcntl(sockfd, F_GETFL, 0);
474 				if (set_blocking(sockfd, true) == -1) {
475 					return (ssize_t)-1;
476 				}
477 				ret = SMB_VFS_RECVFILE(sockfd,
478 							fsp,
479 							offset + total,
480 							N - total);
481 				if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
482 					return (ssize_t)-1;
483 				}
484 				if (ret == -1) {
485 					return (ssize_t)-1;
486 				}
487 				total += ret;
488 				return (ssize_t)total;
489 			}
490 			/* Any other error case. */
491 			if (ret == -1) {
492 				return ret;
493 			}
494 			total += ret;
495 		}
496 		return (ssize_t)total;
497 	}
498 
499 	while (total < N) {
500 		ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
501 				     offset + total);
502 
503 		if (ret == -1)
504 			return -1;
505 		if (ret == 0)
506 			return total;
507 
508 		total += ret;
509 	}
510 	return (ssize_t)total;
511 }
512 /****************************************************************************
513  An allocate file space call using the vfs interface.
514  Allocates space for a file from a filedescriptor.
515  Returns 0 on success, -1 on failure.
516 ****************************************************************************/
517 
vfs_allocate_file_space(files_struct * fsp,uint64_t len)518 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
519 {
520 	int ret;
521 	connection_struct *conn = fsp->conn;
522 	uint64_t space_avail;
523 	uint64_t bsize,dfree,dsize;
524 	NTSTATUS status;
525 	bool ok;
526 
527 	/*
528 	 * Actually try and commit the space on disk....
529 	 */
530 
531 	DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
532 		  fsp_str_dbg(fsp), (double)len));
533 
534 	ok = vfs_valid_pwrite_range((off_t)len, 0);
535 	if (!ok) {
536 		DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len "
537 			 "requested.\n", fsp_str_dbg(fsp)));
538 		errno = EINVAL;
539 		return -1;
540 	}
541 
542 	status = vfs_stat_fsp(fsp);
543 	if (!NT_STATUS_IS_OK(status)) {
544 		return -1;
545 	}
546 
547 	if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
548 		return 0;
549 
550 	if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
551 		/* Shrink - use ftruncate. */
552 
553 		DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
554 			  "size %.0f\n", fsp_str_dbg(fsp),
555 			  (double)fsp->fsp_name->st.st_ex_size));
556 
557 		contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
558 
559 		ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
560 
561 		contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
562 
563 		return ret;
564 	}
565 
566 	/* Grow - we need to test if we have enough space. */
567 
568 	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
569 
570 	if (lp_strict_allocate(SNUM(fsp->conn))) {
571 		/* See if we have a syscall that will allocate beyond
572 		   end-of-file without changing EOF. */
573 		ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
574 					0, len);
575 	} else {
576 		ret = 0;
577 	}
578 
579 	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
580 
581 	if (ret == 0) {
582 		/* We changed the allocation size on disk, but not
583 		   EOF - exactly as required. We're done ! */
584 		return 0;
585 	}
586 
587 	if (ret == -1 && errno == ENOSPC) {
588 		return -1;
589 	}
590 
591 	len -= fsp->fsp_name->st.st_ex_size;
592 	len /= 1024; /* Len is now number of 1k blocks needed. */
593 	space_avail =
594 	    get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
595 	if (space_avail == (uint64_t)-1) {
596 		return -1;
597 	}
598 
599 	DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
600 		  "needed blocks = %.0f, space avail = %.0f\n",
601 		  fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
602 		  (double)space_avail));
603 
604 	if (len > space_avail) {
605 		errno = ENOSPC;
606 		return -1;
607 	}
608 
609 	return 0;
610 }
611 
612 /****************************************************************************
613  A vfs set_filelen call.
614  set the length of a file from a filedescriptor.
615  Returns 0 on success, -1 on failure.
616 ****************************************************************************/
617 
vfs_set_filelen(files_struct * fsp,off_t len)618 int vfs_set_filelen(files_struct *fsp, off_t len)
619 {
620 	int ret;
621 	bool ok;
622 
623 	ok = vfs_valid_pwrite_range(len, 0);
624 	if (!ok) {
625 		errno = EINVAL;
626 		return -1;
627 	}
628 
629 	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
630 
631 	DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
632 		  fsp_str_dbg(fsp), (double)len));
633 	if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
634 		notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
635 			     FILE_NOTIFY_CHANGE_SIZE
636 			     | FILE_NOTIFY_CHANGE_ATTRIBUTES,
637 			     fsp->fsp_name->base_name);
638 	}
639 
640 	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
641 
642 	return ret;
643 }
644 
645 /****************************************************************************
646  A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
647  fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
648  as this is also called from the default SMB_VFS_FTRUNCATE code.
649  Always extends the file size.
650  Returns 0 on success, -1 on failure.
651 ****************************************************************************/
652 
653 #define SPARSE_BUF_WRITE_SIZE (32*1024)
654 
vfs_slow_fallocate(files_struct * fsp,off_t offset,off_t len)655 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
656 {
657 	ssize_t pwrite_ret;
658 	size_t total = 0;
659 	bool ok;
660 
661 	ok = vfs_valid_pwrite_range(offset, len);
662 	if (!ok) {
663 		errno = EINVAL;
664 		return -1;
665 	}
666 
667 	if (!sparse_buf) {
668 		sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
669 		if (!sparse_buf) {
670 			errno = ENOMEM;
671 			return -1;
672 		}
673 	}
674 
675 	while (total < len) {
676 		size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
677 
678 		pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
679 		if (pwrite_ret == -1) {
680 			int saved_errno = errno;
681 			DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
682 				  "%s failed with error %s\n",
683 				  fsp_str_dbg(fsp), strerror(saved_errno)));
684 			errno = saved_errno;
685 			return -1;
686 		}
687 		total += pwrite_ret;
688 	}
689 
690 	return 0;
691 }
692 
693 /****************************************************************************
694  A vfs fill sparse call.
695  Writes zeros from the end of file to len, if len is greater than EOF.
696  Used only by strict_sync.
697  Returns 0 on success, -1 on failure.
698 ****************************************************************************/
699 
vfs_fill_sparse(files_struct * fsp,off_t len)700 int vfs_fill_sparse(files_struct *fsp, off_t len)
701 {
702 	int ret;
703 	NTSTATUS status;
704 	off_t offset;
705 	size_t num_to_write;
706 	bool ok;
707 
708 	ok = vfs_valid_pwrite_range(len, 0);
709 	if (!ok) {
710 		errno = EINVAL;
711 		return -1;
712 	}
713 
714 	status = vfs_stat_fsp(fsp);
715 	if (!NT_STATUS_IS_OK(status)) {
716 		return -1;
717 	}
718 
719 	if (len <= fsp->fsp_name->st.st_ex_size) {
720 		return 0;
721 	}
722 
723 #ifdef S_ISFIFO
724 	if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
725 		return 0;
726 	}
727 #endif
728 
729 	DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
730 		  "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
731 		  (double)fsp->fsp_name->st.st_ex_size, (double)len,
732 		  (double)(len - fsp->fsp_name->st.st_ex_size)));
733 
734 	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
735 
736 	offset = fsp->fsp_name->st.st_ex_size;
737 	num_to_write = len - fsp->fsp_name->st.st_ex_size;
738 
739 	/* Only do this on non-stream file handles. */
740 	if (fsp->base_fsp == NULL) {
741 		/* for allocation try fallocate first. This can fail on some
742 		 * platforms e.g. when the filesystem doesn't support it and no
743 		 * emulation is being done by the libc (like on AIX with JFS1). In that
744 		 * case we do our own emulation. fallocate implementations can
745 		 * return ENOTSUP or EINVAL in cases like that. */
746 		ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
747 		if (ret == -1 && errno == ENOSPC) {
748 			goto out;
749 		}
750 		if (ret == 0) {
751 			goto out;
752 		}
753 		DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
754 			"error %d. Falling back to slow manual allocation\n", ret));
755 	}
756 
757 	ret = vfs_slow_fallocate(fsp, offset, num_to_write);
758 
759  out:
760 
761 	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
762 	return ret;
763 }
764 
765 /*******************************************************************************
766  Set a fd into blocking/nonblocking mode through VFS
767 *******************************************************************************/
768 
vfs_set_blocking(files_struct * fsp,bool set)769 int vfs_set_blocking(files_struct *fsp, bool set)
770 {
771 	int val;
772 #ifdef O_NONBLOCK
773 #define FLAG_TO_SET O_NONBLOCK
774 #else
775 #ifdef SYSV
776 #define FLAG_TO_SET O_NDELAY
777 #else /* BSD */
778 #define FLAG_TO_SET FNDELAY
779 #endif
780 #endif
781 	val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
782 	if (val == -1) {
783 		return -1;
784 	}
785 
786 	if (set) {
787 		val &= ~FLAG_TO_SET;
788 	} else {
789 		val |= FLAG_TO_SET;
790 	}
791 
792 	return SMB_VFS_FCNTL(fsp, F_SETFL, val);
793 #undef FLAG_TO_SET
794 }
795 
796 /****************************************************************************
797  Transfer some data (n bytes) between two file_struct's.
798 ****************************************************************************/
799 
vfs_pread_fn(void * file,void * buf,size_t len,off_t offset)800 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
801 {
802 	struct files_struct *fsp = (struct files_struct *)file;
803 
804 	return SMB_VFS_PREAD(fsp, buf, len, offset);
805 }
806 
vfs_pwrite_fn(void * file,const void * buf,size_t len,off_t offset)807 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
808 {
809 	struct files_struct *fsp = (struct files_struct *)file;
810 
811 	return SMB_VFS_PWRITE(fsp, buf, len, offset);
812 }
813 
vfs_transfer_file(files_struct * in,files_struct * out,off_t n)814 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
815 {
816 	return transfer_file_internal((void *)in, (void *)out, n,
817 				      vfs_pread_fn, vfs_pwrite_fn);
818 }
819 
820 /*******************************************************************
821  A vfs_readdir wrapper which just returns the file name.
822 ********************************************************************/
823 
vfs_readdirname(connection_struct * conn,void * p,SMB_STRUCT_STAT * sbuf,char ** talloced)824 const char *vfs_readdirname(connection_struct *conn, void *p,
825 			    SMB_STRUCT_STAT *sbuf, char **talloced)
826 {
827 	struct dirent *ptr= NULL;
828 	const char *dname;
829 	char *translated;
830 	NTSTATUS status;
831 
832 	if (!p)
833 		return(NULL);
834 
835 	ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
836 	if (!ptr)
837 		return(NULL);
838 
839 	dname = ptr->d_name;
840 
841 
842 #ifdef NEXT2
843 	if (telldir(p) < 0)
844 		return(NULL);
845 #endif
846 
847 #ifdef HAVE_BROKEN_READDIR_NAME
848 	/* using /usr/ucb/cc is BAD */
849 	dname = dname - 2;
850 #endif
851 
852 	status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
853 					talloc_tos(), &translated);
854 	if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
855 		*talloced = NULL;
856 		return dname;
857 	}
858 	*talloced = translated;
859 	if (!NT_STATUS_IS_OK(status)) {
860 		return NULL;
861 	}
862 	return translated;
863 }
864 
865 /*******************************************************************
866  A wrapper for vfs_chdir().
867 ********************************************************************/
868 
vfs_ChDir(connection_struct * conn,const struct smb_filename * smb_fname)869 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
870 {
871 	int ret;
872 	struct smb_filename *cwd = NULL;
873 
874 	if (!LastDir) {
875 		LastDir = SMB_STRDUP("");
876 	}
877 
878 	if (ISDOT(smb_fname->base_name)) {
879 		/*
880 		 * passing a '.' is a noop,
881 		 * and we only expect this after
882 		 * everything is initialized.
883 		 *
884 		 * So the first vfs_ChDir() on a given
885 		 * connection_struct must not be '.'.
886 		 *
887 		 * Note: conn_new() sets
888 		 * conn->cwd_fsp->fh->fd = -1
889 		 * and vfs_ChDir() leaves with
890 		 * conn->cwd_fsp->fh->fd = AT_FDCWD
891 		 * on success!
892 		 */
893 		if (conn->cwd_fsp->fh->fd != AT_FDCWD) {
894 			/*
895 			 * This should never happen and
896 			 * we might change this to
897 			 * SMB_ASSERT() in future.
898 			 */
899 			DBG_ERR("Called with '.' as first operation!\n");
900 			log_stack_trace();
901 			errno = EINVAL;
902 			return -1;
903 		}
904 		return 0;
905 	}
906 
907 	if (smb_fname->base_name[0] == '/' &&
908 	    strcsequal(LastDir,smb_fname->base_name))
909 	{
910 		/*
911 		 * conn->cwd_fsp->fsp_name and the kernel
912 		 * are already correct, but conn->cwd_fsp->fh->fd
913 		 * might still be -1 as initialized in conn_new().
914 		 *
915 		 * This can happen when a client made a 2nd
916 		 * tree connect to a share with the same underlying
917 		 * path (may or may not the same share).
918 		 */
919 		conn->cwd_fsp->fh->fd = AT_FDCWD;
920 		return 0;
921 	}
922 
923 	DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
924 
925 	ret = SMB_VFS_CHDIR(conn, smb_fname);
926 	if (ret != 0) {
927 		return -1;
928 	}
929 
930 	/*
931 	 * Always replace conn->cwd_fsp. We
932 	 * don't know if it's been modified by
933 	 * VFS modules in the stack.
934 	 */
935 
936 	/* conn cache. */
937 	cwd = vfs_GetWd(conn, conn);
938 	if (cwd == NULL) {
939 		/*
940 		 * vfs_GetWd() failed.
941 		 * We must be able to read cwd.
942 		 * Return to original directory
943 		 * and return -1.
944 		 */
945 		int saved_errno = errno;
946 
947 		if (conn->cwd_fsp->fsp_name == NULL) {
948 			/*
949 			 * Failed on the very first chdir()+getwd()
950 			 * for this connection. We can't
951 			 * continue.
952 			 */
953 			smb_panic("conn->cwd getwd failed\n");
954 			/* NOTREACHED */
955 			return -1;
956 		}
957 
958 		/* Return to the previous $cwd. */
959 		ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
960 		if (ret != 0) {
961 			smb_panic("conn->cwd getwd failed\n");
962 			/* NOTREACHED */
963 			return -1;
964 		}
965 		errno = saved_errno;
966 		/* And fail the chdir(). */
967 		return -1;
968 	}
969 
970 	/* vfs_GetWd() succeeded. */
971 	/* Replace global cache. */
972 	SAFE_FREE(LastDir);
973 	LastDir = SMB_STRDUP(smb_fname->base_name);
974 
975 	/*
976 	 * (Indirect) Callers of vfs_ChDir() may still hold references to the
977 	 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
978 	 * callers can use it for the lifetime of the SMB request.
979 	 */
980 	talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
981 
982 	conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
983 	conn->cwd_fsp->fh->fd = AT_FDCWD;
984 
985 	DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
986 
987 	return ret;
988 }
989 
990 /*******************************************************************
991  Return the absolute current directory path - given a UNIX pathname.
992  Note that this path is returned in DOS format, not UNIX
993  format. Note this can be called with conn == NULL.
994 ********************************************************************/
995 
vfs_GetWd(TALLOC_CTX * ctx,connection_struct * conn)996 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
997 {
998         struct smb_filename *current_dir_fname = NULL;
999 	struct file_id key;
1000 	struct smb_filename *smb_fname_dot = NULL;
1001 	struct smb_filename *smb_fname_full = NULL;
1002 	struct smb_filename *result = NULL;
1003 
1004 	if (!lp_getwd_cache()) {
1005 		goto nocache;
1006 	}
1007 
1008 	smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
1009 	if (smb_fname_dot == NULL) {
1010 		errno = ENOMEM;
1011 		goto out;
1012 	}
1013 
1014 	if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
1015 		/*
1016 		 * Known to fail for root: the directory may be NFS-mounted
1017 		 * and exported with root_squash (so has no root access).
1018 		 */
1019 		DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
1020 			 "(NFS problem ?)\n", strerror(errno) ));
1021 		goto nocache;
1022 	}
1023 
1024 	key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1025 
1026 	smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
1027 					smbd_memcache(),
1028 					GETWD_CACHE,
1029 					data_blob_const(&key, sizeof(key)));
1030 
1031 	if (smb_fname_full == NULL) {
1032 		goto nocache;
1033 	}
1034 
1035 	if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1036 	    (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1037 	    (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1038 	    (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1039 		/*
1040 		 * Ok, we're done
1041 		 * Note: smb_fname_full is owned by smbd_memcache()
1042 		 * so we must make a copy to return.
1043 		 */
1044 		result = cp_smb_filename(ctx, smb_fname_full);
1045 		if (result == NULL) {
1046 			errno = ENOMEM;
1047 		}
1048 		goto out;
1049 	}
1050 
1051  nocache:
1052 
1053 	/*
1054 	 * We don't have the information to hand so rely on traditional
1055 	 * methods. The very slow getcwd, which spawns a process on some
1056 	 * systems, or the not quite so bad getwd.
1057 	 */
1058 
1059 	current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1060 	if (current_dir_fname == NULL) {
1061 		DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1062 			  strerror(errno)));
1063 		goto out;
1064 	}
1065 
1066 	if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1067 		key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1068 
1069 		/*
1070 		 * smbd_memcache() will own current_dir_fname after the
1071 		 * memcache_add_talloc call, so we must make
1072 		 * a copy on ctx to return.
1073 		 */
1074 		result = cp_smb_filename(ctx, current_dir_fname);
1075 		if (result == NULL) {
1076 			errno = ENOMEM;
1077 		}
1078 
1079 		/*
1080 		 * Ensure the memory going into the cache
1081 		 * doesn't have a destructor so it can be
1082 		 * cleanly freed.
1083 		 */
1084 		talloc_set_destructor(current_dir_fname, NULL);
1085 
1086 		memcache_add_talloc(smbd_memcache(),
1087 				GETWD_CACHE,
1088 				data_blob_const(&key, sizeof(key)),
1089 				&current_dir_fname);
1090 		/* current_dir_fname is now == NULL here. */
1091 	} else {
1092 		/* current_dir_fname is already allocated on ctx. */
1093 		result = current_dir_fname;
1094 	}
1095 
1096  out:
1097 	TALLOC_FREE(smb_fname_dot);
1098 	/*
1099 	 * Don't free current_dir_fname here. It's either been moved
1100 	 * to the memcache or is being returned in result.
1101 	 */
1102 	return result;
1103 }
1104 
1105 /*******************************************************************
1106  Reduce a file name, removing .. elements and checking that
1107  it is below dir in the hierarchy. This uses realpath.
1108  This function must run as root, and will return names
1109  and valid stat structs that can be checked on open.
1110 ********************************************************************/
1111 
check_reduced_name_with_privilege(connection_struct * conn,const struct smb_filename * smb_fname,struct smb_request * smbreq)1112 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1113 			const struct smb_filename *smb_fname,
1114 			struct smb_request *smbreq)
1115 {
1116 	NTSTATUS status;
1117 	TALLOC_CTX *ctx = talloc_tos();
1118 	const char *conn_rootdir;
1119 	size_t rootdir_len;
1120 	char *dir_name = NULL;
1121 	char *resolved_name = NULL;
1122 	const char *last_component = NULL;
1123 	struct smb_filename *resolved_fname = NULL;
1124 	struct smb_filename *saved_dir_fname = NULL;
1125 	struct smb_filename *smb_fname_cwd = NULL;
1126 	struct privilege_paths *priv_paths = NULL;
1127 	int ret;
1128 
1129 	DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1130 			smb_fname->base_name,
1131 			conn->connectpath));
1132 
1133 
1134 	priv_paths = talloc_zero(smbreq, struct privilege_paths);
1135 	if (!priv_paths) {
1136 		status = NT_STATUS_NO_MEMORY;
1137 		goto err;
1138 	}
1139 
1140 	if (!parent_dirname(ctx, smb_fname->base_name,
1141 			&dir_name, &last_component)) {
1142 		status = NT_STATUS_NO_MEMORY;
1143 		goto err;
1144 	}
1145 
1146 	priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1147 	priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1148 
1149 	if (priv_paths->parent_name.base_name == NULL ||
1150 			priv_paths->file_name.base_name == NULL) {
1151 		status = NT_STATUS_NO_MEMORY;
1152 		goto err;
1153 	}
1154 
1155 	if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1156 		status = map_nt_error_from_unix(errno);
1157 		goto err;
1158 	}
1159 	/* Remember where we were. */
1160 	saved_dir_fname = vfs_GetWd(ctx, conn);
1161 	if (!saved_dir_fname) {
1162 		status = map_nt_error_from_unix(errno);
1163 		goto err;
1164 	}
1165 
1166 	if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1167 		status = map_nt_error_from_unix(errno);
1168 		goto err;
1169 	}
1170 
1171 	smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1172 	if (smb_fname_cwd == NULL) {
1173 		status = NT_STATUS_NO_MEMORY;
1174 		goto err;
1175 	}
1176 
1177 	/* Get the absolute path of the parent directory. */
1178 	resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1179 	if (resolved_fname == NULL) {
1180 		status = map_nt_error_from_unix(errno);
1181 		goto err;
1182 	}
1183 	resolved_name = resolved_fname->base_name;
1184 
1185 	if (*resolved_name != '/') {
1186 		DEBUG(0,("check_reduced_name_with_privilege: realpath "
1187 			"doesn't return absolute paths !\n"));
1188 		status = NT_STATUS_OBJECT_NAME_INVALID;
1189 		goto err;
1190 	}
1191 
1192 	DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1193 		priv_paths->parent_name.base_name,
1194 		resolved_name));
1195 
1196 	/* Now check the stat value is the same. */
1197 	if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1198 		status = map_nt_error_from_unix(errno);
1199 		goto err;
1200 	}
1201 
1202 	/* Ensure we're pointing at the same place. */
1203 	if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1204 		DEBUG(0,("check_reduced_name_with_privilege: "
1205 			"device/inode/uid/gid on directory %s changed. "
1206 			"Denying access !\n",
1207 			priv_paths->parent_name.base_name));
1208 		status = NT_STATUS_ACCESS_DENIED;
1209 		goto err;
1210 	}
1211 
1212 	/* Ensure we're below the connect path. */
1213 
1214 	conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1215 	if (conn_rootdir == NULL) {
1216 		DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1217 			"conn_rootdir\n"));
1218 		status = NT_STATUS_ACCESS_DENIED;
1219 		goto err;
1220 	}
1221 
1222 	rootdir_len = strlen(conn_rootdir);
1223 
1224 	/*
1225 	 * In the case of rootdir_len == 1, we know that conn_rootdir is
1226 	 * "/", and we also know that resolved_name starts with a slash.
1227 	 * So, in this corner case, resolved_name is automatically a
1228 	 * sub-directory of the conn_rootdir. Thus we can skip the string
1229 	 * comparison and the next character checks (which are even
1230 	 * wrong in this case).
1231 	 */
1232 	if (rootdir_len != 1) {
1233 		bool matched;
1234 
1235 		matched = (strncmp(conn_rootdir, resolved_name,
1236 				rootdir_len) == 0);
1237 
1238 		if (!matched || (resolved_name[rootdir_len] != '/' &&
1239 				 resolved_name[rootdir_len] != '\0')) {
1240 			DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1241 				"access attempt: %s is a symlink outside the "
1242 				"share path\n",
1243 				dir_name));
1244 			DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1245 			DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1246 			status = NT_STATUS_ACCESS_DENIED;
1247 			goto err;
1248 		}
1249 	}
1250 
1251 	/* Now ensure that the last component either doesn't
1252 	   exist, or is *NOT* a symlink. */
1253 
1254 	ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1255 	if (ret == -1) {
1256 		/* Errno must be ENOENT for this be ok. */
1257 		if (errno != ENOENT) {
1258 			status = map_nt_error_from_unix(errno);
1259 			DEBUG(2, ("check_reduced_name_with_privilege: "
1260 				"LSTAT on %s failed with %s\n",
1261 				priv_paths->file_name.base_name,
1262 				nt_errstr(status)));
1263 			goto err;
1264 		}
1265 	}
1266 
1267 	if (VALID_STAT(priv_paths->file_name.st) &&
1268 			S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1269 		DEBUG(2, ("check_reduced_name_with_privilege: "
1270 			"Last component %s is a symlink. Denying"
1271 			"access.\n",
1272 			priv_paths->file_name.base_name));
1273 		status = NT_STATUS_ACCESS_DENIED;
1274 		goto err;
1275 	}
1276 
1277 	smbreq->priv_paths = priv_paths;
1278 	status = NT_STATUS_OK;
1279 
1280   err:
1281 
1282 	if (saved_dir_fname != NULL) {
1283 		vfs_ChDir(conn, saved_dir_fname);
1284 		TALLOC_FREE(saved_dir_fname);
1285 	}
1286 	TALLOC_FREE(resolved_fname);
1287 	if (!NT_STATUS_IS_OK(status)) {
1288 		TALLOC_FREE(priv_paths);
1289 	}
1290 	TALLOC_FREE(dir_name);
1291 	return status;
1292 }
1293 
1294 /*******************************************************************
1295  Reduce a file name, removing .. elements and checking that
1296  it is below dir in the hierarchy. This uses realpath.
1297 
1298  If cwd_name == NULL then fname is a client given path relative
1299  to the root path of the share.
1300 
1301  If cwd_name != NULL then fname is a client given path relative
1302  to cwd_name. cwd_name is relative to the root path of the share.
1303 ********************************************************************/
1304 
check_reduced_name(connection_struct * conn,const struct smb_filename * cwd_fname,const struct smb_filename * smb_fname)1305 NTSTATUS check_reduced_name(connection_struct *conn,
1306 				const struct smb_filename *cwd_fname,
1307 				const struct smb_filename *smb_fname)
1308 {
1309 	TALLOC_CTX *ctx = talloc_tos();
1310 	const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1311 	const char *fname = smb_fname->base_name;
1312 	struct smb_filename *resolved_fname;
1313 	char *resolved_name = NULL;
1314 	char *new_fname = NULL;
1315 	bool allow_symlinks = true;
1316 	bool allow_widelinks = false;
1317 
1318 	DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1319 
1320 	resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1321 
1322 	if (resolved_fname == NULL) {
1323 		switch (errno) {
1324 			case ENOTDIR:
1325 				DEBUG(3,("check_reduced_name: Component not a "
1326 					 "directory in getting realpath for "
1327 					 "%s\n", fname));
1328 				return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1329 			case ENOENT:
1330 			{
1331 				char *dir_name = NULL;
1332 				struct smb_filename dir_fname = {0};
1333 				const char *last_component = NULL;
1334 
1335 				/* Last component didn't exist.
1336 				   Remove it and try and canonicalise
1337 				   the directory name. */
1338 				if (!parent_dirname(ctx, fname,
1339 						&dir_name,
1340 						&last_component)) {
1341 					return NT_STATUS_NO_MEMORY;
1342 				}
1343 
1344 				dir_fname = (struct smb_filename)
1345 					{ .base_name = dir_name };
1346 				resolved_fname = SMB_VFS_REALPATH(conn,
1347 							ctx,
1348 							&dir_fname);
1349 				if (resolved_fname == NULL) {
1350 					NTSTATUS status = map_nt_error_from_unix(errno);
1351 
1352 					if (errno == ENOENT || errno == ENOTDIR) {
1353 						status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1354 					}
1355 
1356 					DEBUG(3,("check_reduce_name: "
1357 						 "couldn't get realpath for "
1358 						 "%s (%s)\n",
1359 						fname,
1360 						nt_errstr(status)));
1361 					return status;
1362 				}
1363 				resolved_name = talloc_asprintf(ctx,
1364 						"%s/%s",
1365 						resolved_fname->base_name,
1366 						last_component);
1367 				if (resolved_name == NULL) {
1368 					return NT_STATUS_NO_MEMORY;
1369 				}
1370 				break;
1371 			}
1372 			default:
1373 				DEBUG(3,("check_reduced_name: couldn't get "
1374 					 "realpath for %s\n", fname));
1375 				return map_nt_error_from_unix(errno);
1376 		}
1377 	} else {
1378 		resolved_name = resolved_fname->base_name;
1379 	}
1380 
1381 	DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1382 		  resolved_name));
1383 
1384 	if (*resolved_name != '/') {
1385 		DEBUG(0,("check_reduced_name: realpath doesn't return "
1386 			 "absolute paths !\n"));
1387 		TALLOC_FREE(resolved_fname);
1388 		return NT_STATUS_OBJECT_NAME_INVALID;
1389 	}
1390 
1391 	allow_widelinks = lp_widelinks(SNUM(conn));
1392 	allow_symlinks = lp_follow_symlinks(SNUM(conn));
1393 
1394 	/* Common widelinks and symlinks checks. */
1395 	if (!allow_widelinks || !allow_symlinks) {
1396 		const char *conn_rootdir;
1397 		size_t rootdir_len;
1398 
1399 		conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1400 		if (conn_rootdir == NULL) {
1401 			DEBUG(2, ("check_reduced_name: Could not get "
1402 				"conn_rootdir\n"));
1403 			TALLOC_FREE(resolved_fname);
1404 			return NT_STATUS_ACCESS_DENIED;
1405 		}
1406 
1407 		rootdir_len = strlen(conn_rootdir);
1408 
1409 		/*
1410 		 * In the case of rootdir_len == 1, we know that
1411 		 * conn_rootdir is "/", and we also know that
1412 		 * resolved_name starts with a slash.  So, in this
1413 		 * corner case, resolved_name is automatically a
1414 		 * sub-directory of the conn_rootdir. Thus we can skip
1415 		 * the string comparison and the next character checks
1416 		 * (which are even wrong in this case).
1417 		 */
1418 		if (rootdir_len != 1) {
1419 			bool matched;
1420 
1421 			matched = (strncmp(conn_rootdir, resolved_name,
1422 					rootdir_len) == 0);
1423 			if (!matched || (resolved_name[rootdir_len] != '/' &&
1424 					 resolved_name[rootdir_len] != '\0')) {
1425 				DEBUG(2, ("check_reduced_name: Bad access "
1426 					"attempt: %s is a symlink outside the "
1427 					"share path\n", fname));
1428 				DEBUGADD(2, ("conn_rootdir =%s\n",
1429 					     conn_rootdir));
1430 				DEBUGADD(2, ("resolved_name=%s\n",
1431 					     resolved_name));
1432 				TALLOC_FREE(resolved_fname);
1433 				return NT_STATUS_ACCESS_DENIED;
1434 			}
1435 		}
1436 
1437 		/* Extra checks if all symlinks are disallowed. */
1438 		if (!allow_symlinks) {
1439 			/* fname can't have changed in resolved_path. */
1440 			const char *p = &resolved_name[rootdir_len];
1441 
1442 			/*
1443 			 * UNIX filesystem semantics, names consisting
1444 			 * only of "." or ".." CANNOT be symlinks.
1445 			 */
1446 			if (ISDOT(fname) || ISDOTDOT(fname)) {
1447 				goto out;
1448 			}
1449 
1450 			if (*p != '/') {
1451 				DEBUG(2, ("check_reduced_name: logic error (%c) "
1452 					"in resolved_name: %s\n",
1453 					*p,
1454 					fname));
1455 				TALLOC_FREE(resolved_fname);
1456 				return NT_STATUS_ACCESS_DENIED;
1457 			}
1458 
1459 			p++;
1460 
1461 			/*
1462 			 * If cwd_name is present and not ".",
1463 			 * then fname is relative to that, not
1464 			 * the root of the share. Make sure the
1465 			 * path we check is the one the client
1466 			 * sent (cwd_name+fname).
1467 			 */
1468 			if (cwd_name != NULL && !ISDOT(cwd_name)) {
1469 				new_fname = talloc_asprintf(ctx,
1470 							"%s/%s",
1471 							cwd_name,
1472 							fname);
1473 				if (new_fname == NULL) {
1474 					TALLOC_FREE(resolved_fname);
1475 					return NT_STATUS_NO_MEMORY;
1476 				}
1477 				fname = new_fname;
1478 			}
1479 
1480 			if (strcmp(fname, p)!=0) {
1481 				DEBUG(2, ("check_reduced_name: Bad access "
1482 					"attempt: %s is a symlink to %s\n",
1483 					  fname, p));
1484 				TALLOC_FREE(resolved_fname);
1485 				TALLOC_FREE(new_fname);
1486 				return NT_STATUS_ACCESS_DENIED;
1487 			}
1488 		}
1489 	}
1490 
1491   out:
1492 
1493 	DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1494 	TALLOC_FREE(resolved_fname);
1495 	TALLOC_FREE(new_fname);
1496 	return NT_STATUS_OK;
1497 }
1498 
1499 /**
1500  * XXX: This is temporary and there should be no callers of this once
1501  * smb_filename is plumbed through all path based operations.
1502  *
1503  * Called when we know stream name parsing has already been done.
1504  */
vfs_stat_smb_basename(struct connection_struct * conn,const struct smb_filename * smb_fname_in,SMB_STRUCT_STAT * psbuf)1505 int vfs_stat_smb_basename(struct connection_struct *conn,
1506 			const struct smb_filename *smb_fname_in,
1507 			SMB_STRUCT_STAT *psbuf)
1508 {
1509 	struct smb_filename smb_fname = {
1510 		.base_name = discard_const_p(char, smb_fname_in->base_name),
1511 		.flags = smb_fname_in->flags
1512 	};
1513 	int ret;
1514 
1515 	if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1516 		ret = SMB_VFS_LSTAT(conn, &smb_fname);
1517 	} else {
1518 		ret = SMB_VFS_STAT(conn, &smb_fname);
1519 	}
1520 
1521 	if (ret != -1) {
1522 		*psbuf = smb_fname.st;
1523 	}
1524 	return ret;
1525 }
1526 
1527 /**
1528  * Ensure LSTAT is called for POSIX paths.
1529  */
1530 
vfs_stat_fsp(files_struct * fsp)1531 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1532 {
1533 	int ret;
1534 	struct stat_ex saved_stat = fsp->fsp_name->st;
1535 
1536 	if(fsp->fh->fd == -1) {
1537 		if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1538 			ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1539 		} else {
1540 			ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1541 		}
1542 	} else {
1543 		ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1544 	}
1545 	if (ret == -1) {
1546 		return map_nt_error_from_unix(errno);
1547 	}
1548 	update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1549 	return NT_STATUS_OK;
1550 }
1551 
init_smb_file_time(struct smb_file_time * ft)1552 void init_smb_file_time(struct smb_file_time *ft)
1553 {
1554 	*ft = (struct smb_file_time) {
1555 		.atime = make_omit_timespec(),
1556 		.ctime = make_omit_timespec(),
1557 		.mtime = make_omit_timespec(),
1558 		.create_time = make_omit_timespec()
1559 	};
1560 }
1561 
1562 /**
1563  * Initialize num_streams and streams, then call VFS op streaminfo
1564  */
vfs_streaminfo(connection_struct * conn,struct files_struct * fsp,const struct smb_filename * smb_fname,TALLOC_CTX * mem_ctx,unsigned int * num_streams,struct stream_struct ** streams)1565 NTSTATUS vfs_streaminfo(connection_struct *conn,
1566 			struct files_struct *fsp,
1567 			const struct smb_filename *smb_fname,
1568 			TALLOC_CTX *mem_ctx,
1569 			unsigned int *num_streams,
1570 			struct stream_struct **streams)
1571 {
1572 	*num_streams = 0;
1573 	*streams = NULL;
1574 	return SMB_VFS_STREAMINFO(conn,
1575 			fsp,
1576 			smb_fname,
1577 			mem_ctx,
1578 			num_streams,
1579 			streams);
1580 }
1581 
1582 /*
1583  * This is just a helper to make
1584  * users of vfs_fake_fd() more symetric
1585  */
vfs_fake_fd_close(int fd)1586 int vfs_fake_fd_close(int fd)
1587 {
1588 	return close(fd);
1589 }
1590 
1591 /*
1592   generate a file_id from a stat structure
1593  */
vfs_file_id_from_sbuf(connection_struct * conn,const SMB_STRUCT_STAT * sbuf)1594 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1595 {
1596 	return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1597 }
1598 
smb_vfs_call_connect(struct vfs_handle_struct * handle,const char * service,const char * user)1599 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1600 			 const char *service, const char *user)
1601 {
1602 	VFS_FIND(connect);
1603 	return handle->fns->connect_fn(handle, service, user);
1604 }
1605 
smb_vfs_call_disconnect(struct vfs_handle_struct * handle)1606 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1607 {
1608 	VFS_FIND(disconnect);
1609 	handle->fns->disconnect_fn(handle);
1610 }
1611 
smb_vfs_call_disk_free(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uint64_t * bsize,uint64_t * dfree,uint64_t * dsize)1612 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1613 				const struct smb_filename *smb_fname,
1614 				uint64_t *bsize,
1615 				uint64_t *dfree,
1616 				uint64_t *dsize)
1617 {
1618 	VFS_FIND(disk_free);
1619 	return handle->fns->disk_free_fn(handle, smb_fname,
1620 			bsize, dfree, dsize);
1621 }
1622 
smb_vfs_call_get_quota(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,enum SMB_QUOTA_TYPE qtype,unid_t id,SMB_DISK_QUOTA * qt)1623 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1624 				const struct smb_filename *smb_fname,
1625 				enum SMB_QUOTA_TYPE qtype,
1626 				unid_t id,
1627 				SMB_DISK_QUOTA *qt)
1628 {
1629 	VFS_FIND(get_quota);
1630 	return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1631 }
1632 
smb_vfs_call_set_quota(struct vfs_handle_struct * handle,enum SMB_QUOTA_TYPE qtype,unid_t id,SMB_DISK_QUOTA * qt)1633 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1634 			   enum SMB_QUOTA_TYPE qtype, unid_t id,
1635 			   SMB_DISK_QUOTA *qt)
1636 {
1637 	VFS_FIND(set_quota);
1638 	return handle->fns->set_quota_fn(handle, qtype, id, qt);
1639 }
1640 
smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct * handle,struct files_struct * fsp,struct shadow_copy_data * shadow_copy_data,bool labels)1641 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1642 				      struct files_struct *fsp,
1643 				      struct shadow_copy_data *shadow_copy_data,
1644 				      bool labels)
1645 {
1646 	VFS_FIND(get_shadow_copy_data);
1647 	return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1648 						    shadow_copy_data,
1649 						    labels);
1650 }
smb_vfs_call_statvfs(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,struct vfs_statvfs_struct * statbuf)1651 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1652 			const struct smb_filename *smb_fname,
1653 			struct vfs_statvfs_struct *statbuf)
1654 {
1655 	VFS_FIND(statvfs);
1656 	return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1657 }
1658 
smb_vfs_call_fs_capabilities(struct vfs_handle_struct * handle,enum timestamp_set_resolution * p_ts_res)1659 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1660 			enum timestamp_set_resolution *p_ts_res)
1661 {
1662 	VFS_FIND(fs_capabilities);
1663 	return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1664 }
1665 
smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct * handle,struct dfs_GetDFSReferral * r)1666 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1667 					struct dfs_GetDFSReferral *r)
1668 {
1669 	VFS_FIND(get_dfs_referrals);
1670 	return handle->fns->get_dfs_referrals_fn(handle, r);
1671 }
1672 
smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,const struct referral * reflist,size_t referral_count)1673 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1674 				struct files_struct *dirfsp,
1675 				const struct smb_filename *smb_fname,
1676 				const struct referral *reflist,
1677 				size_t referral_count)
1678 {
1679 	VFS_FIND(create_dfs_pathat);
1680 	return handle->fns->create_dfs_pathat_fn(handle,
1681 						dirfsp,
1682 						smb_fname,
1683 						reflist,
1684 						referral_count);
1685 }
1686 
smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct files_struct * dirfsp,const struct smb_filename * smb_fname,struct referral ** ppreflist,size_t * preferral_count)1687 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1688 				TALLOC_CTX *mem_ctx,
1689 				struct files_struct *dirfsp,
1690 				const struct smb_filename *smb_fname,
1691 				struct referral **ppreflist,
1692 				size_t *preferral_count)
1693 {
1694 	VFS_FIND(read_dfs_pathat);
1695 	return handle->fns->read_dfs_pathat_fn(handle,
1696 						mem_ctx,
1697 						dirfsp,
1698 						smb_fname,
1699 						ppreflist,
1700 						preferral_count);
1701 }
1702 
smb_vfs_call_opendir(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * mask,uint32_t attributes)1703 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1704 					const struct smb_filename *smb_fname,
1705 					const char *mask,
1706 					uint32_t attributes)
1707 {
1708 	VFS_FIND(opendir);
1709 	return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1710 }
1711 
smb_vfs_call_fdopendir(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * mask,uint32_t attributes)1712 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1713 					struct files_struct *fsp,
1714 					const char *mask,
1715 					uint32_t attributes)
1716 {
1717 	VFS_FIND(fdopendir);
1718 	return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1719 }
1720 
smb_vfs_call_readdir(struct vfs_handle_struct * handle,DIR * dirp,SMB_STRUCT_STAT * sbuf)1721 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1722 					      DIR *dirp,
1723 					      SMB_STRUCT_STAT *sbuf)
1724 {
1725 	VFS_FIND(readdir);
1726 	return handle->fns->readdir_fn(handle, dirp, sbuf);
1727 }
1728 
smb_vfs_call_seekdir(struct vfs_handle_struct * handle,DIR * dirp,long offset)1729 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1730 			  DIR *dirp, long offset)
1731 {
1732 	VFS_FIND(seekdir);
1733 	handle->fns->seekdir_fn(handle, dirp, offset);
1734 }
1735 
smb_vfs_call_telldir(struct vfs_handle_struct * handle,DIR * dirp)1736 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1737 			  DIR *dirp)
1738 {
1739 	VFS_FIND(telldir);
1740 	return handle->fns->telldir_fn(handle, dirp);
1741 }
1742 
smb_vfs_call_rewind_dir(struct vfs_handle_struct * handle,DIR * dirp)1743 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1744 			     DIR *dirp)
1745 {
1746 	VFS_FIND(rewind_dir);
1747 	handle->fns->rewind_dir_fn(handle, dirp);
1748 }
1749 
smb_vfs_call_mkdirat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,mode_t mode)1750 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1751 			struct files_struct *dirfsp,
1752 			const struct smb_filename *smb_fname,
1753 			mode_t mode)
1754 {
1755 	VFS_FIND(mkdirat);
1756 	return handle->fns->mkdirat_fn(handle,
1757 			dirfsp,
1758 			smb_fname,
1759 			mode);
1760 }
1761 
smb_vfs_call_closedir(struct vfs_handle_struct * handle,DIR * dir)1762 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1763 			  DIR *dir)
1764 {
1765 	VFS_FIND(closedir);
1766 	return handle->fns->closedir_fn(handle, dir);
1767 }
1768 
smb_vfs_call_open(struct vfs_handle_struct * handle,struct smb_filename * smb_fname,struct files_struct * fsp,int flags,mode_t mode)1769 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1770 		      struct smb_filename *smb_fname, struct files_struct *fsp,
1771 		      int flags, mode_t mode)
1772 {
1773 	VFS_FIND(open);
1774 	return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1775 }
1776 
smb_vfs_call_create_file(struct vfs_handle_struct * handle,struct smb_request * req,uint16_t root_dir_fid,struct smb_filename * smb_fname,uint32_t access_mask,uint32_t share_access,uint32_t create_disposition,uint32_t create_options,uint32_t file_attributes,uint32_t oplock_request,const struct smb2_lease * lease,uint64_t allocation_size,uint32_t private_flags,struct security_descriptor * sd,struct ea_list * ea_list,files_struct ** result,int * pinfo,const struct smb2_create_blobs * in_context_blobs,struct smb2_create_blobs * out_context_blobs)1777 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1778 				  struct smb_request *req,
1779 				  uint16_t root_dir_fid,
1780 				  struct smb_filename *smb_fname,
1781 				  uint32_t access_mask,
1782 				  uint32_t share_access,
1783 				  uint32_t create_disposition,
1784 				  uint32_t create_options,
1785 				  uint32_t file_attributes,
1786 				  uint32_t oplock_request,
1787 				  const struct smb2_lease *lease,
1788 				  uint64_t allocation_size,
1789 				  uint32_t private_flags,
1790 				  struct security_descriptor *sd,
1791 				  struct ea_list *ea_list,
1792 				  files_struct **result,
1793 				  int *pinfo,
1794 				  const struct smb2_create_blobs *in_context_blobs,
1795 				  struct smb2_create_blobs *out_context_blobs)
1796 {
1797 	VFS_FIND(create_file);
1798 	return handle->fns->create_file_fn(
1799 		handle, req, root_dir_fid, smb_fname, access_mask,
1800 		share_access, create_disposition, create_options,
1801 		file_attributes, oplock_request, lease, allocation_size,
1802 		private_flags, sd, ea_list,
1803 		result, pinfo, in_context_blobs, out_context_blobs);
1804 }
1805 
smb_vfs_call_close(struct vfs_handle_struct * handle,struct files_struct * fsp)1806 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1807 		       struct files_struct *fsp)
1808 {
1809 	VFS_FIND(close);
1810 	return handle->fns->close_fn(handle, fsp);
1811 }
1812 
smb_vfs_call_pread(struct vfs_handle_struct * handle,struct files_struct * fsp,void * data,size_t n,off_t offset)1813 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1814 			   struct files_struct *fsp, void *data, size_t n,
1815 			   off_t offset)
1816 {
1817 	VFS_FIND(pread);
1818 	return handle->fns->pread_fn(handle, fsp, data, n, offset);
1819 }
1820 
1821 struct smb_vfs_call_pread_state {
1822 	ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1823 	ssize_t retval;
1824 	struct vfs_aio_state vfs_aio_state;
1825 };
1826 
1827 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1828 
smb_vfs_call_pread_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct files_struct * fsp,void * data,size_t n,off_t offset)1829 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1830 					   TALLOC_CTX *mem_ctx,
1831 					   struct tevent_context *ev,
1832 					   struct files_struct *fsp,
1833 					   void *data,
1834 					   size_t n, off_t offset)
1835 {
1836 	struct tevent_req *req, *subreq;
1837 	struct smb_vfs_call_pread_state *state;
1838 
1839 	req = tevent_req_create(mem_ctx, &state,
1840 				struct smb_vfs_call_pread_state);
1841 	if (req == NULL) {
1842 		return NULL;
1843 	}
1844 	VFS_FIND(pread_send);
1845 	state->recv_fn = handle->fns->pread_recv_fn;
1846 
1847 	subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1848 					    offset);
1849 	if (tevent_req_nomem(subreq, req)) {
1850 		return tevent_req_post(req, ev);
1851 	}
1852 	tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1853 	return req;
1854 }
1855 
smb_vfs_call_pread_done(struct tevent_req * subreq)1856 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1857 {
1858 	struct tevent_req *req = tevent_req_callback_data(
1859 		subreq, struct tevent_req);
1860 	struct smb_vfs_call_pread_state *state = tevent_req_data(
1861 		req, struct smb_vfs_call_pread_state);
1862 
1863 	state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1864 	TALLOC_FREE(subreq);
1865 	if (state->retval == -1) {
1866 		tevent_req_error(req, state->vfs_aio_state.error);
1867 		return;
1868 	}
1869 	tevent_req_done(req);
1870 }
1871 
SMB_VFS_PREAD_RECV(struct tevent_req * req,struct vfs_aio_state * vfs_aio_state)1872 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1873 			   struct vfs_aio_state *vfs_aio_state)
1874 {
1875 	struct smb_vfs_call_pread_state *state = tevent_req_data(
1876 		req, struct smb_vfs_call_pread_state);
1877 	ssize_t retval;
1878 
1879 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1880 		tevent_req_received(req);
1881 		return -1;
1882 	}
1883 	*vfs_aio_state = state->vfs_aio_state;
1884 	retval = state->retval;
1885 	tevent_req_received(req);
1886 	return retval;
1887 }
1888 
smb_vfs_call_pwrite(struct vfs_handle_struct * handle,struct files_struct * fsp,const void * data,size_t n,off_t offset)1889 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1890 			    struct files_struct *fsp, const void *data,
1891 			    size_t n, off_t offset)
1892 {
1893 	VFS_FIND(pwrite);
1894 	return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1895 }
1896 
1897 struct smb_vfs_call_pwrite_state {
1898 	ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1899 	ssize_t retval;
1900 	struct vfs_aio_state vfs_aio_state;
1901 };
1902 
1903 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1904 
smb_vfs_call_pwrite_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct files_struct * fsp,const void * data,size_t n,off_t offset)1905 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1906 					    TALLOC_CTX *mem_ctx,
1907 					    struct tevent_context *ev,
1908 					    struct files_struct *fsp,
1909 					    const void *data,
1910 					    size_t n, off_t offset)
1911 {
1912 	struct tevent_req *req, *subreq;
1913 	struct smb_vfs_call_pwrite_state *state;
1914 
1915 	req = tevent_req_create(mem_ctx, &state,
1916 				struct smb_vfs_call_pwrite_state);
1917 	if (req == NULL) {
1918 		return NULL;
1919 	}
1920 	VFS_FIND(pwrite_send);
1921 	state->recv_fn = handle->fns->pwrite_recv_fn;
1922 
1923 	subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1924 					     offset);
1925 	if (tevent_req_nomem(subreq, req)) {
1926 		return tevent_req_post(req, ev);
1927 	}
1928 	tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1929 	return req;
1930 }
1931 
smb_vfs_call_pwrite_done(struct tevent_req * subreq)1932 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1933 {
1934 	struct tevent_req *req = tevent_req_callback_data(
1935 		subreq, struct tevent_req);
1936 	struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1937 		req, struct smb_vfs_call_pwrite_state);
1938 
1939 	state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1940 	TALLOC_FREE(subreq);
1941 	if (state->retval == -1) {
1942 		tevent_req_error(req, state->vfs_aio_state.error);
1943 		return;
1944 	}
1945 	tevent_req_done(req);
1946 }
1947 
SMB_VFS_PWRITE_RECV(struct tevent_req * req,struct vfs_aio_state * vfs_aio_state)1948 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1949 			    struct vfs_aio_state *vfs_aio_state)
1950 {
1951 	struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1952 		req, struct smb_vfs_call_pwrite_state);
1953 	ssize_t retval;
1954 
1955 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1956 		tevent_req_received(req);
1957 		return -1;
1958 	}
1959 	*vfs_aio_state = state->vfs_aio_state;
1960 	retval = state->retval;
1961 	tevent_req_received(req);
1962 	return retval;
1963 }
1964 
smb_vfs_call_lseek(struct vfs_handle_struct * handle,struct files_struct * fsp,off_t offset,int whence)1965 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1966 			     struct files_struct *fsp, off_t offset,
1967 			     int whence)
1968 {
1969 	VFS_FIND(lseek);
1970 	return handle->fns->lseek_fn(handle, fsp, offset, whence);
1971 }
1972 
smb_vfs_call_sendfile(struct vfs_handle_struct * handle,int tofd,files_struct * fromfsp,const DATA_BLOB * header,off_t offset,size_t count)1973 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1974 			      files_struct *fromfsp, const DATA_BLOB *header,
1975 			      off_t offset, size_t count)
1976 {
1977 	VFS_FIND(sendfile);
1978 	return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1979 					count);
1980 }
1981 
smb_vfs_call_recvfile(struct vfs_handle_struct * handle,int fromfd,files_struct * tofsp,off_t offset,size_t count)1982 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1983 			      files_struct *tofsp, off_t offset,
1984 			      size_t count)
1985 {
1986 	VFS_FIND(recvfile);
1987 	return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1988 }
1989 
smb_vfs_call_renameat(struct vfs_handle_struct * handle,files_struct * srcfsp,const struct smb_filename * smb_fname_src,files_struct * dstfsp,const struct smb_filename * smb_fname_dst)1990 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
1991 			files_struct *srcfsp,
1992 			const struct smb_filename *smb_fname_src,
1993 			files_struct *dstfsp,
1994 			const struct smb_filename *smb_fname_dst)
1995 {
1996 	VFS_FIND(renameat);
1997 	return handle->fns->renameat_fn(handle,
1998 				srcfsp,
1999 				smb_fname_src,
2000 				dstfsp,
2001 				smb_fname_dst);
2002 }
2003 
2004 struct smb_vfs_call_fsync_state {
2005 	int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
2006 	int retval;
2007 	struct vfs_aio_state vfs_aio_state;
2008 };
2009 
2010 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
2011 
smb_vfs_call_fsync_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct files_struct * fsp)2012 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
2013 					   TALLOC_CTX *mem_ctx,
2014 					   struct tevent_context *ev,
2015 					   struct files_struct *fsp)
2016 {
2017 	struct tevent_req *req, *subreq;
2018 	struct smb_vfs_call_fsync_state *state;
2019 
2020 	req = tevent_req_create(mem_ctx, &state,
2021 				struct smb_vfs_call_fsync_state);
2022 	if (req == NULL) {
2023 		return NULL;
2024 	}
2025 	VFS_FIND(fsync_send);
2026 	state->recv_fn = handle->fns->fsync_recv_fn;
2027 
2028 	subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
2029 	if (tevent_req_nomem(subreq, req)) {
2030 		return tevent_req_post(req, ev);
2031 	}
2032 	tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
2033 	return req;
2034 }
2035 
smb_vfs_call_fsync_done(struct tevent_req * subreq)2036 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
2037 {
2038 	struct tevent_req *req = tevent_req_callback_data(
2039 		subreq, struct tevent_req);
2040 	struct smb_vfs_call_fsync_state *state = tevent_req_data(
2041 		req, struct smb_vfs_call_fsync_state);
2042 
2043 	state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2044 	TALLOC_FREE(subreq);
2045 	if (state->retval == -1) {
2046 		tevent_req_error(req, state->vfs_aio_state.error);
2047 		return;
2048 	}
2049 	tevent_req_done(req);
2050 }
2051 
SMB_VFS_FSYNC_RECV(struct tevent_req * req,struct vfs_aio_state * vfs_aio_state)2052 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
2053 {
2054 	struct smb_vfs_call_fsync_state *state = tevent_req_data(
2055 		req, struct smb_vfs_call_fsync_state);
2056 	ssize_t retval;
2057 
2058 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2059 		tevent_req_received(req);
2060 		return -1;
2061 	}
2062 	*vfs_aio_state = state->vfs_aio_state;
2063 	retval = state->retval;
2064 	tevent_req_received(req);
2065 	return retval;
2066 }
2067 
2068 /*
2069  * Synchronous version of fsync, built from backend
2070  * async VFS primitives. Uses a temporary sub-event
2071  * context (NOT NESTED).
2072  */
2073 
smb_vfs_fsync_sync(files_struct * fsp)2074 int smb_vfs_fsync_sync(files_struct *fsp)
2075 {
2076 	TALLOC_CTX *frame = talloc_stackframe();
2077 	struct tevent_req *req = NULL;
2078 	struct vfs_aio_state aio_state = { 0 };
2079 	int ret = -1;
2080 	bool ok;
2081 	struct tevent_context *ev = samba_tevent_context_init(frame);
2082 
2083 	if (ev == NULL) {
2084 		goto out;
2085 	}
2086 
2087 	req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
2088 	if (req == NULL) {
2089 		goto out;
2090 	}
2091 
2092 	ok = tevent_req_poll(req, ev);
2093 	if (!ok) {
2094 		goto out;
2095 	}
2096 
2097 	ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
2098 
2099   out:
2100 
2101 	TALLOC_FREE(frame);
2102 	if (aio_state.error != 0) {
2103 		errno = aio_state.error;
2104 	}
2105 	return ret;
2106 }
2107 
smb_vfs_call_stat(struct vfs_handle_struct * handle,struct smb_filename * smb_fname)2108 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2109 		      struct smb_filename *smb_fname)
2110 {
2111 	VFS_FIND(stat);
2112 	return handle->fns->stat_fn(handle, smb_fname);
2113 }
2114 
smb_vfs_call_fstat(struct vfs_handle_struct * handle,struct files_struct * fsp,SMB_STRUCT_STAT * sbuf)2115 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2116 		       struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2117 {
2118 	VFS_FIND(fstat);
2119 	return handle->fns->fstat_fn(handle, fsp, sbuf);
2120 }
2121 
smb_vfs_call_lstat(struct vfs_handle_struct * handle,struct smb_filename * smb_filename)2122 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2123 		       struct smb_filename *smb_filename)
2124 {
2125 	VFS_FIND(lstat);
2126 	return handle->fns->lstat_fn(handle, smb_filename);
2127 }
2128 
smb_vfs_call_get_alloc_size(struct vfs_handle_struct * handle,struct files_struct * fsp,const SMB_STRUCT_STAT * sbuf)2129 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2130 				     struct files_struct *fsp,
2131 				     const SMB_STRUCT_STAT *sbuf)
2132 {
2133 	VFS_FIND(get_alloc_size);
2134 	return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2135 }
2136 
smb_vfs_call_unlinkat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,int flags)2137 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2138 			struct files_struct *dirfsp,
2139 			const struct smb_filename *smb_fname,
2140 			int flags)
2141 {
2142 	VFS_FIND(unlinkat);
2143 	return handle->fns->unlinkat_fn(handle,
2144 			dirfsp,
2145 			smb_fname,
2146 			flags);
2147 }
2148 
smb_vfs_call_chmod(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,mode_t mode)2149 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2150 			const struct smb_filename *smb_fname,
2151 			mode_t mode)
2152 {
2153 	VFS_FIND(chmod);
2154 	return handle->fns->chmod_fn(handle, smb_fname, mode);
2155 }
2156 
smb_vfs_call_fchmod(struct vfs_handle_struct * handle,struct files_struct * fsp,mode_t mode)2157 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2158 			struct files_struct *fsp, mode_t mode)
2159 {
2160 	VFS_FIND(fchmod);
2161 	return handle->fns->fchmod_fn(handle, fsp, mode);
2162 }
2163 
smb_vfs_call_fchown(struct vfs_handle_struct * handle,struct files_struct * fsp,uid_t uid,gid_t gid)2164 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2165 			struct files_struct *fsp, uid_t uid, gid_t gid)
2166 {
2167 	VFS_FIND(fchown);
2168 	return handle->fns->fchown_fn(handle, fsp, uid, gid);
2169 }
2170 
smb_vfs_call_lchown(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uid_t uid,gid_t gid)2171 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2172 			const struct smb_filename *smb_fname,
2173 			uid_t uid,
2174 			gid_t gid)
2175 {
2176 	VFS_FIND(lchown);
2177 	return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2178 }
2179 
smb_vfs_call_chdir(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname)2180 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2181 			const struct smb_filename *smb_fname)
2182 {
2183 	VFS_FIND(chdir);
2184 	return handle->fns->chdir_fn(handle, smb_fname);
2185 }
2186 
smb_vfs_call_getwd(struct vfs_handle_struct * handle,TALLOC_CTX * ctx)2187 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2188 				TALLOC_CTX *ctx)
2189 {
2190 	VFS_FIND(getwd);
2191 	return handle->fns->getwd_fn(handle, ctx);
2192 }
2193 
smb_vfs_call_ntimes(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,struct smb_file_time * ft)2194 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2195 			const struct smb_filename *smb_fname,
2196 			struct smb_file_time *ft)
2197 {
2198 	VFS_FIND(ntimes);
2199 	return handle->fns->ntimes_fn(handle, smb_fname, ft);
2200 }
2201 
smb_vfs_call_ftruncate(struct vfs_handle_struct * handle,struct files_struct * fsp,off_t offset)2202 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2203 			   struct files_struct *fsp, off_t offset)
2204 {
2205 	VFS_FIND(ftruncate);
2206 	return handle->fns->ftruncate_fn(handle, fsp, offset);
2207 }
2208 
smb_vfs_call_fallocate(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t mode,off_t offset,off_t len)2209 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2210 			   struct files_struct *fsp,
2211 			   uint32_t mode,
2212 			   off_t offset,
2213 			   off_t len)
2214 {
2215 	VFS_FIND(fallocate);
2216 	return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2217 }
2218 
smb_vfs_call_kernel_flock(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t share_mode,uint32_t access_mask)2219 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2220 			      struct files_struct *fsp, uint32_t share_mode,
2221 			      uint32_t access_mask)
2222 {
2223 	VFS_FIND(kernel_flock);
2224 	return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2225 					 access_mask);
2226 }
2227 
smb_vfs_call_fcntl(struct vfs_handle_struct * handle,struct files_struct * fsp,int cmd,...)2228 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2229 		       struct files_struct *fsp, int cmd, ...)
2230 {
2231 	int result;
2232 	va_list cmd_arg;
2233 
2234 	VFS_FIND(fcntl);
2235 
2236 	va_start(cmd_arg, cmd);
2237 	result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2238 	va_end(cmd_arg);
2239 
2240 	return result;
2241 }
2242 
smb_vfs_call_linux_setlease(struct vfs_handle_struct * handle,struct files_struct * fsp,int leasetype)2243 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2244 				struct files_struct *fsp, int leasetype)
2245 {
2246 	VFS_FIND(linux_setlease);
2247 	return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2248 }
2249 
smb_vfs_call_symlinkat(struct vfs_handle_struct * handle,const char * link_target,struct files_struct * dirfsp,const struct smb_filename * new_smb_fname)2250 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2251 			const char *link_target,
2252 			struct files_struct *dirfsp,
2253 			const struct smb_filename *new_smb_fname)
2254 {
2255 	VFS_FIND(symlinkat);
2256 	return handle->fns->symlinkat_fn(handle,
2257 				link_target,
2258 				dirfsp,
2259 				new_smb_fname);
2260 }
2261 
smb_vfs_call_readlinkat(struct vfs_handle_struct * handle,files_struct * dirfsp,const struct smb_filename * smb_fname,char * buf,size_t bufsiz)2262 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2263 			files_struct *dirfsp,
2264 			const struct smb_filename *smb_fname,
2265 			char *buf,
2266 			size_t bufsiz)
2267 {
2268 	VFS_FIND(readlinkat);
2269 	return handle->fns->readlinkat_fn(handle,
2270 				dirfsp,
2271 				smb_fname,
2272 				buf,
2273 				bufsiz);
2274 }
2275 
smb_vfs_call_linkat(struct vfs_handle_struct * handle,struct files_struct * srcfsp,const struct smb_filename * old_smb_fname,struct files_struct * dstfsp,const struct smb_filename * new_smb_fname,int flags)2276 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2277 			struct files_struct *srcfsp,
2278 			const struct smb_filename *old_smb_fname,
2279 			struct files_struct *dstfsp,
2280 			const struct smb_filename *new_smb_fname,
2281 			int flags)
2282 {
2283 	VFS_FIND(linkat);
2284 	return handle->fns->linkat_fn(handle,
2285 				srcfsp,
2286 				old_smb_fname,
2287 				dstfsp,
2288 				new_smb_fname,
2289 				flags);
2290 }
2291 
smb_vfs_call_mknodat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,mode_t mode,SMB_DEV_T dev)2292 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2293 			struct files_struct *dirfsp,
2294 			const struct smb_filename *smb_fname,
2295 			mode_t mode,
2296 			SMB_DEV_T dev)
2297 {
2298 	VFS_FIND(mknodat);
2299 	return handle->fns->mknodat_fn(handle,
2300 				dirfsp,
2301 				smb_fname,
2302 				mode,
2303 				dev);
2304 }
2305 
smb_vfs_call_realpath(struct vfs_handle_struct * handle,TALLOC_CTX * ctx,const struct smb_filename * smb_fname)2306 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2307 			TALLOC_CTX *ctx,
2308 			const struct smb_filename *smb_fname)
2309 {
2310 	VFS_FIND(realpath);
2311 	return handle->fns->realpath_fn(handle, ctx, smb_fname);
2312 }
2313 
smb_vfs_call_chflags(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,unsigned int flags)2314 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2315 			const struct smb_filename *smb_fname,
2316 			unsigned int flags)
2317 {
2318 	VFS_FIND(chflags);
2319 	return handle->fns->chflags_fn(handle, smb_fname, flags);
2320 }
2321 
smb_vfs_call_file_id_create(struct vfs_handle_struct * handle,const SMB_STRUCT_STAT * sbuf)2322 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2323 					   const SMB_STRUCT_STAT *sbuf)
2324 {
2325 	VFS_FIND(file_id_create);
2326 	return handle->fns->file_id_create_fn(handle, sbuf);
2327 }
2328 
smb_vfs_call_fs_file_id(struct vfs_handle_struct * handle,const SMB_STRUCT_STAT * sbuf)2329 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2330 				 const SMB_STRUCT_STAT *sbuf)
2331 {
2332 	VFS_FIND(fs_file_id);
2333 	return handle->fns->fs_file_id_fn(handle, sbuf);
2334 }
2335 
smb_vfs_call_streaminfo(struct vfs_handle_struct * handle,struct files_struct * fsp,const struct smb_filename * smb_fname,TALLOC_CTX * mem_ctx,unsigned int * num_streams,struct stream_struct ** streams)2336 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2337 				 struct files_struct *fsp,
2338 				 const struct smb_filename *smb_fname,
2339 				 TALLOC_CTX *mem_ctx,
2340 				 unsigned int *num_streams,
2341 				 struct stream_struct **streams)
2342 {
2343 	VFS_FIND(streaminfo);
2344 	return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2345 					  num_streams, streams);
2346 }
2347 
smb_vfs_call_get_real_filename(struct vfs_handle_struct * handle,const char * path,const char * name,TALLOC_CTX * mem_ctx,char ** found_name)2348 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2349 				   const char *path, const char *name,
2350 				   TALLOC_CTX *mem_ctx, char **found_name)
2351 {
2352 	VFS_FIND(get_real_filename);
2353 	return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2354 						 found_name);
2355 }
2356 
smb_vfs_call_connectpath(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname)2357 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2358 				 const struct smb_filename *smb_fname)
2359 {
2360 	VFS_FIND(connectpath);
2361 	return handle->fns->connectpath_fn(handle, smb_fname);
2362 }
2363 
smb_vfs_call_strict_lock_check(struct vfs_handle_struct * handle,struct files_struct * fsp,struct lock_struct * plock)2364 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2365 				    struct files_struct *fsp,
2366 				    struct lock_struct *plock)
2367 {
2368 	VFS_FIND(strict_lock_check);
2369 	return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2370 }
2371 
smb_vfs_call_translate_name(struct vfs_handle_struct * handle,const char * name,enum vfs_translate_direction direction,TALLOC_CTX * mem_ctx,char ** mapped_name)2372 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2373 				     const char *name,
2374 				     enum vfs_translate_direction direction,
2375 				     TALLOC_CTX *mem_ctx,
2376 				     char **mapped_name)
2377 {
2378 	VFS_FIND(translate_name);
2379 	return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2380 					      mapped_name);
2381 }
2382 
smb_vfs_call_fsctl(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * ctx,uint32_t function,uint16_t req_flags,const uint8_t * in_data,uint32_t in_len,uint8_t ** out_data,uint32_t max_out_len,uint32_t * out_len)2383 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2384 			    struct files_struct *fsp,
2385 			    TALLOC_CTX *ctx,
2386 			    uint32_t function,
2387 			    uint16_t req_flags,
2388 			    const uint8_t *in_data,
2389 			    uint32_t in_len,
2390 			    uint8_t **out_data,
2391 			    uint32_t max_out_len,
2392 			    uint32_t *out_len)
2393 {
2394 	VFS_FIND(fsctl);
2395 	return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2396 				     in_data, in_len, out_data, max_out_len,
2397 				     out_len);
2398 }
2399 
smb_vfs_call_get_dos_attributes(struct vfs_handle_struct * handle,struct smb_filename * smb_fname,uint32_t * dosmode)2400 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2401 					 struct smb_filename *smb_fname,
2402 					 uint32_t *dosmode)
2403 {
2404 	VFS_FIND(get_dos_attributes);
2405 	return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2406 }
2407 
smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t * dosmode)2408 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2409 					  struct files_struct *fsp,
2410 					  uint32_t *dosmode)
2411 {
2412 	VFS_FIND(fget_dos_attributes);
2413 	return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2414 }
2415 
smb_vfs_call_set_dos_attributes(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uint32_t dosmode)2416 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2417 					 const struct smb_filename *smb_fname,
2418 					 uint32_t dosmode)
2419 {
2420 	VFS_FIND(set_dos_attributes);
2421 	return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2422 }
2423 
smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t dosmode)2424 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2425 					  struct files_struct *fsp,
2426 					  uint32_t dosmode)
2427 {
2428 	VFS_FIND(set_dos_attributes);
2429 	return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2430 }
2431 
smb_vfs_call_offload_read_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t fsctl,uint32_t ttl,off_t offset,size_t to_copy)2432 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2433 						  struct tevent_context *ev,
2434 						  struct vfs_handle_struct *handle,
2435 						  struct files_struct *fsp,
2436 						  uint32_t fsctl,
2437 						  uint32_t ttl,
2438 						  off_t offset,
2439 						  size_t to_copy)
2440 {
2441 	VFS_FIND(offload_read_send);
2442 	return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2443 						 fsp, fsctl,
2444 						 ttl, offset, to_copy);
2445 }
2446 
smb_vfs_call_offload_read_recv(struct tevent_req * req,struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,DATA_BLOB * token_blob)2447 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2448 					struct vfs_handle_struct *handle,
2449 					TALLOC_CTX *mem_ctx,
2450 					DATA_BLOB *token_blob)
2451 {
2452 	VFS_FIND(offload_read_recv);
2453 	return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2454 }
2455 
smb_vfs_call_offload_write_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,uint32_t fsctl,DATA_BLOB * token,off_t transfer_offset,struct files_struct * dest_fsp,off_t dest_off,off_t num)2456 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2457 						   TALLOC_CTX *mem_ctx,
2458 						   struct tevent_context *ev,
2459 						   uint32_t fsctl,
2460 						   DATA_BLOB *token,
2461 						   off_t transfer_offset,
2462 						   struct files_struct *dest_fsp,
2463 						   off_t dest_off,
2464 						   off_t num)
2465 {
2466 	VFS_FIND(offload_write_send);
2467 	return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2468 					       token, transfer_offset,
2469 					       dest_fsp, dest_off, num);
2470 }
2471 
smb_vfs_call_offload_write_recv(struct vfs_handle_struct * handle,struct tevent_req * req,off_t * copied)2472 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2473 					 struct tevent_req *req,
2474 					 off_t *copied)
2475 {
2476 	VFS_FIND(offload_write_recv);
2477 	return handle->fns->offload_write_recv_fn(handle, req, copied);
2478 }
2479 
2480 struct smb_vfs_call_get_dos_attributes_state {
2481 	files_struct *dir_fsp;
2482 	NTSTATUS (*recv_fn)(struct tevent_req *req,
2483 			    struct vfs_aio_state *aio_state,
2484 			    uint32_t *dosmode);
2485 	struct vfs_aio_state aio_state;
2486 	uint32_t dos_attributes;
2487 };
2488 
2489 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2490 
smb_vfs_call_get_dos_attributes_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct vfs_handle_struct * handle,files_struct * dir_fsp,struct smb_filename * smb_fname)2491 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2492 			TALLOC_CTX *mem_ctx,
2493 			struct tevent_context *ev,
2494 			struct vfs_handle_struct *handle,
2495 			files_struct *dir_fsp,
2496 			struct smb_filename *smb_fname)
2497 {
2498 	struct tevent_req *req = NULL;
2499 	struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2500 	struct tevent_req *subreq = NULL;
2501 
2502 	req = tevent_req_create(mem_ctx, &state,
2503 				struct smb_vfs_call_get_dos_attributes_state);
2504 	if (req == NULL) {
2505 		return NULL;
2506 	}
2507 
2508 	VFS_FIND(get_dos_attributes_send);
2509 
2510 	*state = (struct smb_vfs_call_get_dos_attributes_state) {
2511 		.dir_fsp = dir_fsp,
2512 		.recv_fn = handle->fns->get_dos_attributes_recv_fn,
2513 	};
2514 
2515 	subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2516 							 ev,
2517 							 handle,
2518 							 dir_fsp,
2519 							 smb_fname);
2520 	if (tevent_req_nomem(subreq, req)) {
2521 		return tevent_req_post(req, ev);
2522 	}
2523 	tevent_req_defer_callback(req, ev);
2524 
2525 	tevent_req_set_callback(subreq,
2526 				smb_vfs_call_get_dos_attributes_done,
2527 				req);
2528 
2529 	return req;
2530 }
2531 
smb_vfs_call_get_dos_attributes_done(struct tevent_req * subreq)2532 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2533 {
2534 	struct tevent_req *req =
2535 		tevent_req_callback_data(subreq,
2536 		struct tevent_req);
2537 	struct smb_vfs_call_get_dos_attributes_state *state =
2538 		tevent_req_data(req,
2539 		struct smb_vfs_call_get_dos_attributes_state);
2540 	NTSTATUS status;
2541 	bool ok;
2542 
2543 	/*
2544 	 * Make sure we run as the user again
2545 	 */
2546 	ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2547 	SMB_ASSERT(ok);
2548 
2549 	status = state->recv_fn(subreq,
2550 				&state->aio_state,
2551 				&state->dos_attributes);
2552 	TALLOC_FREE(subreq);
2553 	if (tevent_req_nterror(req, status)) {
2554 		return;
2555 	}
2556 
2557 	tevent_req_done(req);
2558 }
2559 
smb_vfs_call_get_dos_attributes_recv(struct tevent_req * req,struct vfs_aio_state * aio_state,uint32_t * dos_attributes)2560 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2561 		struct tevent_req *req,
2562 		struct vfs_aio_state *aio_state,
2563 		uint32_t *dos_attributes)
2564 {
2565 	struct smb_vfs_call_get_dos_attributes_state *state =
2566 		tevent_req_data(req,
2567 		struct smb_vfs_call_get_dos_attributes_state);
2568 	NTSTATUS status;
2569 
2570 	if (tevent_req_is_nterror(req, &status)) {
2571 		tevent_req_received(req);
2572 		return status;
2573 	}
2574 
2575 	*aio_state = state->aio_state;
2576 	*dos_attributes = state->dos_attributes;
2577 	tevent_req_received(req);
2578 	return NT_STATUS_OK;
2579 }
2580 
smb_vfs_call_get_compression(vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct files_struct * fsp,struct smb_filename * smb_fname,uint16_t * _compression_fmt)2581 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2582 				      TALLOC_CTX *mem_ctx,
2583 				      struct files_struct *fsp,
2584 				      struct smb_filename *smb_fname,
2585 				      uint16_t *_compression_fmt)
2586 {
2587 	VFS_FIND(get_compression);
2588 	return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2589 					       _compression_fmt);
2590 }
2591 
smb_vfs_call_set_compression(vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct files_struct * fsp,uint16_t compression_fmt)2592 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2593 				      TALLOC_CTX *mem_ctx,
2594 				      struct files_struct *fsp,
2595 				      uint16_t compression_fmt)
2596 {
2597 	VFS_FIND(set_compression);
2598 	return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2599 					       compression_fmt);
2600 }
2601 
smb_vfs_call_snap_check_path(vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,const char * service_path,char ** base_volume)2602 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2603 				      TALLOC_CTX *mem_ctx,
2604 				      const char *service_path,
2605 				      char **base_volume)
2606 {
2607 	VFS_FIND(snap_check_path);
2608 	return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2609 					       base_volume);
2610 }
2611 
smb_vfs_call_snap_create(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,const char * base_volume,time_t * tstamp,bool rw,char ** base_path,char ** snap_path)2612 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2613 				  TALLOC_CTX *mem_ctx,
2614 				  const char *base_volume,
2615 				  time_t *tstamp,
2616 				  bool rw,
2617 				  char **base_path,
2618 				  char **snap_path)
2619 {
2620 	VFS_FIND(snap_create);
2621 	return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2622 					   rw, base_path, snap_path);
2623 }
2624 
smb_vfs_call_snap_delete(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,char * base_path,char * snap_path)2625 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2626 				  TALLOC_CTX *mem_ctx,
2627 				  char *base_path,
2628 				  char *snap_path)
2629 {
2630 	VFS_FIND(snap_delete);
2631 	return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2632 					   snap_path);
2633 }
2634 
smb_vfs_call_fget_nt_acl(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t security_info,TALLOC_CTX * mem_ctx,struct security_descriptor ** ppdesc)2635 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2636 				  struct files_struct *fsp,
2637 				  uint32_t security_info,
2638 				  TALLOC_CTX *mem_ctx,
2639 				  struct security_descriptor **ppdesc)
2640 {
2641 	VFS_FIND(fget_nt_acl);
2642 	return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2643 					   mem_ctx, ppdesc);
2644 }
2645 
smb_vfs_call_get_nt_acl(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uint32_t security_info,TALLOC_CTX * mem_ctx,struct security_descriptor ** ppdesc)2646 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2647 				 const struct smb_filename *smb_fname,
2648 				 uint32_t security_info,
2649 				 TALLOC_CTX *mem_ctx,
2650 				 struct security_descriptor **ppdesc)
2651 {
2652 	VFS_FIND(get_nt_acl);
2653 	return handle->fns->get_nt_acl_fn(handle,
2654 				smb_fname,
2655 				security_info,
2656 				mem_ctx,
2657 				ppdesc);
2658 }
2659 
smb_vfs_call_fset_nt_acl(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t security_info_sent,const struct security_descriptor * psd)2660 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2661 				  struct files_struct *fsp,
2662 				  uint32_t security_info_sent,
2663 				  const struct security_descriptor *psd)
2664 {
2665 	VFS_FIND(fset_nt_acl);
2666 	return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2667 					   psd);
2668 }
2669 
smb_vfs_call_audit_file(struct vfs_handle_struct * handle,struct smb_filename * file,struct security_acl * sacl,uint32_t access_requested,uint32_t access_denied)2670 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2671 				 struct smb_filename *file,
2672 				 struct security_acl *sacl,
2673 				 uint32_t access_requested,
2674 				 uint32_t access_denied)
2675 {
2676 	VFS_FIND(audit_file);
2677 	return handle->fns->audit_file_fn(handle,
2678 					  file,
2679 					  sacl,
2680 					  access_requested,
2681 					  access_denied);
2682 }
2683 
smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,SMB_ACL_TYPE_T type,TALLOC_CTX * mem_ctx)2684 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2685 					const struct smb_filename *smb_fname,
2686 					SMB_ACL_TYPE_T type,
2687 					TALLOC_CTX *mem_ctx)
2688 {
2689 	VFS_FIND(sys_acl_get_file);
2690 	return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2691 }
2692 
smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * mem_ctx)2693 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2694 				      struct files_struct *fsp,
2695 				      TALLOC_CTX *mem_ctx)
2696 {
2697 	VFS_FIND(sys_acl_get_fd);
2698 	return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2699 }
2700 
smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,TALLOC_CTX * mem_ctx,char ** blob_description,DATA_BLOB * blob)2701 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2702 				const struct smb_filename *smb_fname,
2703 				TALLOC_CTX *mem_ctx,
2704 				char **blob_description,
2705 				DATA_BLOB *blob)
2706 {
2707 	VFS_FIND(sys_acl_blob_get_file);
2708 	return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2709 			mem_ctx, blob_description, blob);
2710 }
2711 
smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * mem_ctx,char ** blob_description,DATA_BLOB * blob)2712 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2713 				     struct files_struct *fsp,
2714 				     TALLOC_CTX *mem_ctx,
2715 				     char **blob_description,
2716 				     DATA_BLOB *blob)
2717 {
2718 	VFS_FIND(sys_acl_blob_get_fd);
2719 	return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2720 }
2721 
smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,SMB_ACL_TYPE_T acltype,SMB_ACL_T theacl)2722 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2723 				const struct smb_filename *smb_fname,
2724 				SMB_ACL_TYPE_T acltype,
2725 				SMB_ACL_T theacl)
2726 {
2727 	VFS_FIND(sys_acl_set_file);
2728 	return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2729 				acltype, theacl);
2730 }
2731 
smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct * handle,struct files_struct * fsp,SMB_ACL_T theacl)2732 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2733 				struct files_struct *fsp, SMB_ACL_T theacl)
2734 {
2735 	VFS_FIND(sys_acl_set_fd);
2736 	return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2737 }
2738 
smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname)2739 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2740 				const struct smb_filename *smb_fname)
2741 {
2742 	VFS_FIND(sys_acl_delete_def_file);
2743 	return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2744 }
2745 
smb_vfs_call_getxattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * name,void * value,size_t size)2746 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2747 				const struct smb_filename *smb_fname,
2748 				const char *name,
2749 				void *value,
2750 				size_t size)
2751 {
2752 	VFS_FIND(getxattr);
2753 	return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2754 }
2755 
2756 
2757 struct smb_vfs_call_getxattrat_state {
2758 	files_struct *dir_fsp;
2759 	ssize_t (*recv_fn)(struct tevent_req *req,
2760 			   struct vfs_aio_state *aio_state,
2761 			   TALLOC_CTX *mem_ctx,
2762 			   uint8_t **xattr_value);
2763 	ssize_t retval;
2764 	uint8_t *xattr_value;
2765 	struct vfs_aio_state aio_state;
2766 };
2767 
2768 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2769 
smb_vfs_call_getxattrat_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct vfs_handle_struct * handle,files_struct * dir_fsp,const struct smb_filename * smb_fname,const char * xattr_name,size_t alloc_hint)2770 struct tevent_req *smb_vfs_call_getxattrat_send(
2771 			TALLOC_CTX *mem_ctx,
2772 			struct tevent_context *ev,
2773 			struct vfs_handle_struct *handle,
2774 			files_struct *dir_fsp,
2775 			const struct smb_filename *smb_fname,
2776 			const char *xattr_name,
2777 			size_t alloc_hint)
2778 {
2779 	struct tevent_req *req = NULL;
2780 	struct smb_vfs_call_getxattrat_state *state = NULL;
2781 	struct tevent_req *subreq = NULL;
2782 
2783 	req = tevent_req_create(mem_ctx, &state,
2784 				struct smb_vfs_call_getxattrat_state);
2785 	if (req == NULL) {
2786 		return NULL;
2787 	}
2788 
2789 	VFS_FIND(getxattrat_send);
2790 
2791 	*state = (struct smb_vfs_call_getxattrat_state) {
2792 		.dir_fsp = dir_fsp,
2793 		.recv_fn = handle->fns->getxattrat_recv_fn,
2794 	};
2795 
2796 	subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2797 						 ev,
2798 						 handle,
2799 						 dir_fsp,
2800 						 smb_fname,
2801 						 xattr_name,
2802 						 alloc_hint);
2803 	if (tevent_req_nomem(subreq, req)) {
2804 		return tevent_req_post(req, ev);
2805 	}
2806 	tevent_req_defer_callback(req, ev);
2807 
2808 	tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2809 	return req;
2810 }
2811 
smb_vfs_call_getxattrat_done(struct tevent_req * subreq)2812 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2813 {
2814 	struct tevent_req *req = tevent_req_callback_data(
2815 		subreq, struct tevent_req);
2816 	struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2817 		req, struct smb_vfs_call_getxattrat_state);
2818 	bool ok;
2819 
2820 	/*
2821 	 * Make sure we run as the user again
2822 	 */
2823 	ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2824 	SMB_ASSERT(ok);
2825 
2826 	state->retval = state->recv_fn(subreq,
2827 				       &state->aio_state,
2828 				       state,
2829 				       &state->xattr_value);
2830 	TALLOC_FREE(subreq);
2831 	if (state->retval == -1) {
2832 		tevent_req_error(req, state->aio_state.error);
2833 		return;
2834 	}
2835 
2836 	tevent_req_done(req);
2837 }
2838 
smb_vfs_call_getxattrat_recv(struct tevent_req * req,struct vfs_aio_state * aio_state,TALLOC_CTX * mem_ctx,uint8_t ** xattr_value)2839 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2840 				     struct vfs_aio_state *aio_state,
2841 				     TALLOC_CTX *mem_ctx,
2842 				     uint8_t **xattr_value)
2843 {
2844 	struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2845 		req, struct smb_vfs_call_getxattrat_state);
2846 	size_t xattr_size;
2847 
2848 	if (tevent_req_is_unix_error(req, &aio_state->error)) {
2849 		tevent_req_received(req);
2850 		return -1;
2851 	}
2852 
2853 	*aio_state = state->aio_state;
2854 	xattr_size = state->retval;
2855 	if (xattr_value != NULL) {
2856 		*xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2857 	}
2858 
2859 	tevent_req_received(req);
2860 	return xattr_size;
2861 }
2862 
smb_vfs_call_fgetxattr(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * name,void * value,size_t size)2863 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2864 			       struct files_struct *fsp, const char *name,
2865 			       void *value, size_t size)
2866 {
2867 	VFS_FIND(fgetxattr);
2868 	return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2869 }
2870 
smb_vfs_call_listxattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,char * list,size_t size)2871 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2872 				const struct smb_filename *smb_fname,
2873 				char *list,
2874 				size_t size)
2875 {
2876 	VFS_FIND(listxattr);
2877 	return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2878 }
2879 
smb_vfs_call_flistxattr(struct vfs_handle_struct * handle,struct files_struct * fsp,char * list,size_t size)2880 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2881 				struct files_struct *fsp, char *list,
2882 				size_t size)
2883 {
2884 	VFS_FIND(flistxattr);
2885 	return handle->fns->flistxattr_fn(handle, fsp, list, size);
2886 }
2887 
smb_vfs_call_removexattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * name)2888 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2889 				const struct smb_filename *smb_fname,
2890 				const char *name)
2891 {
2892 	VFS_FIND(removexattr);
2893 	return handle->fns->removexattr_fn(handle, smb_fname, name);
2894 }
2895 
smb_vfs_call_fremovexattr(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * name)2896 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2897 			      struct files_struct *fsp, const char *name)
2898 {
2899 	VFS_FIND(fremovexattr);
2900 	return handle->fns->fremovexattr_fn(handle, fsp, name);
2901 }
2902 
smb_vfs_call_setxattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * name,const void * value,size_t size,int flags)2903 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2904 			const struct smb_filename *smb_fname,
2905 			const char *name,
2906 			const void *value,
2907 			size_t size,
2908 			int flags)
2909 {
2910 	VFS_FIND(setxattr);
2911 	return handle->fns->setxattr_fn(handle, smb_fname,
2912 			name, value, size, flags);
2913 }
2914 
smb_vfs_call_fsetxattr(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * name,const void * value,size_t size,int flags)2915 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2916 			   struct files_struct *fsp, const char *name,
2917 			   const void *value, size_t size, int flags)
2918 {
2919 	VFS_FIND(fsetxattr);
2920 	return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2921 }
2922 
smb_vfs_call_aio_force(struct vfs_handle_struct * handle,struct files_struct * fsp)2923 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2924 			    struct files_struct *fsp)
2925 {
2926 	VFS_FIND(aio_force);
2927 	return handle->fns->aio_force_fn(handle, fsp);
2928 }
2929 
smb_vfs_call_durable_cookie(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * mem_ctx,DATA_BLOB * cookie)2930 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2931 				     struct files_struct *fsp,
2932 				     TALLOC_CTX *mem_ctx,
2933 				     DATA_BLOB *cookie)
2934 {
2935 	VFS_FIND(durable_cookie);
2936 	return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2937 }
2938 
smb_vfs_call_durable_disconnect(struct vfs_handle_struct * handle,struct files_struct * fsp,const DATA_BLOB old_cookie,TALLOC_CTX * mem_ctx,DATA_BLOB * new_cookie)2939 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2940 					 struct files_struct *fsp,
2941 					 const DATA_BLOB old_cookie,
2942 					 TALLOC_CTX *mem_ctx,
2943 					 DATA_BLOB *new_cookie)
2944 {
2945 	VFS_FIND(durable_disconnect);
2946 	return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2947 					          mem_ctx, new_cookie);
2948 }
2949 
smb_vfs_call_durable_reconnect(struct vfs_handle_struct * handle,struct smb_request * smb1req,struct smbXsrv_open * op,const DATA_BLOB old_cookie,TALLOC_CTX * mem_ctx,struct files_struct ** fsp,DATA_BLOB * new_cookie)2950 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2951 					struct smb_request *smb1req,
2952 					struct smbXsrv_open *op,
2953 					const DATA_BLOB old_cookie,
2954 					TALLOC_CTX *mem_ctx,
2955 					struct files_struct **fsp,
2956 					DATA_BLOB *new_cookie)
2957 {
2958 	VFS_FIND(durable_reconnect);
2959 	return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2960 					         old_cookie, mem_ctx, fsp,
2961 					         new_cookie);
2962 }
2963 
smb_vfs_call_readdir_attr(struct vfs_handle_struct * handle,const struct smb_filename * fname,TALLOC_CTX * mem_ctx,struct readdir_attr_data ** attr_data)2964 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2965 				   const struct smb_filename *fname,
2966 				   TALLOC_CTX *mem_ctx,
2967 				   struct readdir_attr_data **attr_data)
2968 {
2969 	VFS_FIND(readdir_attr);
2970 	return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
2971 }
2972