--- /dev/null
+<samba:parameter name="smbd max xattr size"
+ context="S"
+ type="integer"
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+ <para>
+ This parameter controls the maximum size of extended attributes
+ that may be written to the server as EAs or as alternate data
+ streams if vfs_streams_xattr is enabled. The maximum size of
+ extended attributes depends on the Samba server's operating system
+ and the underlying filesystem. The Linux VFS currently sets an
+ upper boundary of 64 KiB per extended attribute. FreeBSD does not
+ set a practical upper limit, but since pread() and pwrite() are not
+ possible via the extattr on FreeBSD, it is not recommended to
+ increase this value above a few MiB.
+
+ If a client attempts to write an overly-large alternate datastream,
+ the Samba server will return STATUS_FILESYSTEM_LIMITATION.
+ If this error is encountered, users may try increasing the maximum
+ size supported for xattr writes. If this is not possible, and
+ writes are from a MacOS client and to an AFP_Resource extended
+ attribute, the user may enable the vfs_fruit module and configure
+ to allow stream writes for AFP_Resource to an alternative storage
+ location. See vfs_fruit documentation for further details.
+ </para>
+</description>
+<value type="default">65536</value>
+</samba:parameter>
"client protection",
"default");
+ lpcfg_do_global_parameter(lp_ctx,
+ "smbd max xattr size",
+ "65536");
+
for (i = 0; parm_table[i].label; i++) {
if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
lp_ctx->flags[i] |= FLAG_DEFAULT;
return -1;
}
+ if ((offset + n) >= lp_smbd_max_xattr_size(SNUM(handle->conn))) {
+ /*
+ * Requested write is beyond what can be read based on
+ * samba configuration.
+ * ReFS returns STATUS_FILESYSTEM_LIMITATION, which causes
+ * entire file to be skipped by File Explorer. VFAT returns
+ * NT_STATUS_OBJECT_NAME_COLLISION causes user to be prompted
+ * to skip writing metadata, but copy data.
+ */
+ DBG_ERR("Write to xattr [%s] on file [%s] exceeds maximum "
+ "supported extended attribute size. "
+ "Depending on filesystem type and operating system "
+ "(OS) specifics, this value may be increased using "
+ "the value of the parameter: "
+ "smbd max xattr size = <bytes>. Consult OS and "
+ "filesystem manpages prior to increasing this limit.\n",
+ sio->xattr_name, sio->base);
+ errno = EOVERFLOW;
+ return -1;
+ }
+
/* Create an smb_filename with stream_name == NULL. */
smb_fname_base = synthetic_smb_fname(talloc_tos(),
sio->base,
.map_hidden = false,
.map_archive = true,
.store_dos_attributes = true,
+ .smbd_max_xattr_size = 65536,
.dmapi_support = false,
.locking = true,
.strict_locking = Auto,
files_struct *fsp = state->fsp;
if (nwritten == -1) {
- status = map_nt_error_from_unix(err);
+ if (err == EOVERFLOW &&
+ is_ntfs_stream_smb_fname(fsp->fsp_name)) {
+ status = NT_STATUS_FILE_SYSTEM_LIMITATION;
+ } else {
+ status = map_nt_error_from_unix(err);
+ }
DEBUG(2, ("smb2_write failed: %s, file %s, "
"length=%lu offset=%lu nwritten=-1: %s\n",
size_t attr_size = 256;
char *val = NULL;
ssize_t sizeret;
+ size_t max_xattr_size = lp_smbd_max_xattr_size(SNUM(conn));
again:
ea_name, val, attr_size);
}
- if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
- attr_size = 65536;
+ if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
+ attr_size = max_xattr_size;
goto again;
}
*/
TALLOC_FREE(listp);
continue;
+ } else if (listp->ea.value.length > 65536) {
+ /*
+ * SMB clients may report error with file
+ * if large EA is presented to them.
+ */
+ DBG_ERR("EA [%s] on file [%s] exceeds "
+ "maximum permitted EA size of 64KiB: %zu\n.",
+ listp->ea.name, fsp_str_dbg(fsp),
+ listp->ea.value.length);
+ TALLOC_FREE(listp);
+ continue;
}
push_ascii_fstring(dos_ea_name, listp->ea.name);