CVE-2023-0614 ldb: Centralise checking for inaccessible matches
[Samba.git] / source3 / modules / vfs_error_inject.c
blobdca8783edafcaeea55f8cd49006e784685e753ef
1 /*
2 * Unix SMB/CIFS implementation.
3 * Samba VFS module for error injection in VFS calls
4 * Copyright (C) Christof Schmitt 2017
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "smbd/smbd.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_VFS
26 struct unix_error_map {
27 const char *err_str;
28 int error;
29 } unix_error_map_array[] = {
30 { "ESTALE", ESTALE },
31 { "EBADF", EBADF },
32 { "EINTR", EINTR },
33 { "EACCES", EACCES },
36 static int find_unix_error_from_string(const char *err_str)
38 size_t i;
40 for (i = 0; i < ARRAY_SIZE(unix_error_map_array); i++) {
41 struct unix_error_map *m = &unix_error_map_array[i];
43 if (strequal(err_str, m->err_str)) {
44 return m->error;
48 return 0;
51 static int inject_unix_error(const char *vfs_func, vfs_handle_struct *handle)
53 const char *err_str;
55 err_str = lp_parm_const_string(SNUM(handle->conn),
56 "error_inject", vfs_func, NULL);
58 if (err_str != NULL) {
59 int error;
61 error = find_unix_error_from_string(err_str);
62 if (error != 0) {
63 DBG_WARNING("Returning error %s for VFS function %s\n",
64 err_str, vfs_func);
65 return error;
68 if (strequal(err_str, "panic")) {
69 DBG_ERR("Panic in VFS function %s\n", vfs_func);
70 smb_panic("error_inject");
73 DBG_ERR("Unknown error inject %s requested "
74 "for vfs function %s\n", err_str, vfs_func);
77 return 0;
80 static int vfs_error_inject_chdir(vfs_handle_struct *handle,
81 const struct smb_filename *smb_fname)
83 int error;
85 error = inject_unix_error("chdir", handle);
86 if (error != 0) {
87 errno = error;
88 return -1;
91 return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
94 static ssize_t vfs_error_inject_pwrite(vfs_handle_struct *handle,
95 files_struct *fsp,
96 const void *data,
97 size_t n,
98 off_t offset)
100 int error;
102 error = inject_unix_error("pwrite", handle);
103 if (error != 0) {
104 errno = error;
105 return -1;
108 return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
111 static int vfs_error_inject_openat(struct vfs_handle_struct *handle,
112 const struct files_struct *dirfsp,
113 const struct smb_filename *smb_fname,
114 files_struct *fsp,
115 int flags,
116 mode_t mode)
118 int error = inject_unix_error("openat", handle);
120 if (!fsp->fsp_flags.is_pathref && error != 0) {
121 errno = error;
122 return -1;
124 return SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, flags, mode);
127 static int vfs_error_inject_unlinkat(struct vfs_handle_struct *handle,
128 struct files_struct *dirfsp,
129 const struct smb_filename *smb_fname,
130 int flags)
132 struct smb_filename *full_fname = NULL;
133 struct smb_filename *parent_fname = NULL;
134 int error = inject_unix_error("unlinkat", handle);
135 int ret;
136 NTSTATUS status;
138 if (error == 0) {
139 return SMB_VFS_NEXT_UNLINKAT(handle, dirfsp, smb_fname, flags);
142 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
143 dirfsp,
144 smb_fname);
145 if (full_fname == NULL) {
146 return -1;
149 status = SMB_VFS_PARENT_PATHNAME(handle->conn,
150 full_fname, /* TALLOC_CTX. */
151 full_fname,
152 &parent_fname,
153 NULL);
154 if (!NT_STATUS_IS_OK(status)) {
155 TALLOC_FREE(full_fname);
156 errno = map_errno_from_nt_status(status);
157 return -1;
160 ret = SMB_VFS_STAT(handle->conn, parent_fname);
161 if (ret != 0) {
162 TALLOC_FREE(full_fname);
163 return -1;
166 if (parent_fname->st.st_ex_uid == get_current_uid(dirfsp->conn)) {
167 return SMB_VFS_NEXT_UNLINKAT(handle, dirfsp, smb_fname, flags);
170 errno = error;
171 return -1;
174 static struct vfs_fn_pointers vfs_error_inject_fns = {
175 .chdir_fn = vfs_error_inject_chdir,
176 .pwrite_fn = vfs_error_inject_pwrite,
177 .openat_fn = vfs_error_inject_openat,
178 .unlinkat_fn = vfs_error_inject_unlinkat,
181 static_decl_vfs;
182 NTSTATUS vfs_error_inject_init(TALLOC_CTX *ctx)
184 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "error_inject",
185 &vfs_error_inject_fns);