Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAS-120362 / Ensure that commonly requested xattrs are in SA #243

Open
wants to merge 1 commit into
base: stable/angelfish
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 122 additions & 2 deletions source3/modules/vfs_streams_xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ struct streams_xattr_config {
const char *prefix;
size_t prefix_len;
bool store_stream_type;
bool seed_builtin_attrs;
int xattr_compat_bytes;
char *afpinfo_name;
char *afpresource_name;
};

struct stream_io {
Expand All @@ -46,6 +49,20 @@ struct stream_io {
vfs_handle_struct *handle;
};

const char EMPTY_XATTR[64] = {0};

static bool is_builtin_attr_name(const char *name,
struct streams_xattr_config *config)
{
if ((strcmp(name, SAMBA_XATTR_DOS_ATTRIB) == 0) ||
(strcmp(name, config->afpinfo_name) == 0) ||

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these elements in the struct get checked for NULL before it reaches this function? I presume they do.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gets checked in streams_xattr_connect()

	if (config->afpresource_name == NULL) {
		DBG_ERR("talloc_asprintf() failed\n");
		return -1;
	}

If tree connect fails, then session won't get this far.

(strcmp(name, config->afpresource_name) == 0)) {
return true;
}

return false;
}

static ssize_t get_xattr_size_fsp(vfs_handle_struct *handle,
struct files_struct *fsp,
const char *xattr_name)
Expand Down Expand Up @@ -957,6 +974,28 @@ static int streams_xattr_connect(vfs_handle_struct *handle,

config->xattr_compat_bytes = xattr_compat ? 0 : 1;

config->afpinfo_name = talloc_asprintf(config, "%s%s%s",
prefix, "AFP_AfpInfo", config->store_stream_type ? ":$DATA" : ""
);
if (config->afpinfo_name == NULL) {
DBG_ERR("talloc_asprintf() failed\n");
return -1;
}

config->afpresource_name = talloc_asprintf(config, "%s%s%s",
prefix, "AFP_Resource", config->store_stream_type ? ":$DATA" : ""
);

if (config->afpresource_name == NULL) {
DBG_ERR("talloc_asprintf() failed\n");
return -1;
}

config->seed_builtin_attrs = lp_parm_bool(SNUM(handle->conn),
"streams_xattr",
"seed_builtin_attrs",
false);

SMB_VFS_HANDLE_SET_DATA(handle, config,
NULL, struct stream_xattr_config,
return -1);
Expand Down Expand Up @@ -1387,6 +1426,73 @@ static int streams_xattr_fchmod(vfs_handle_struct *handle,
return 0;
}

static int seed_builtin_attr(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *name,
bool as_root)
{
int rv;

if (!CAN_WRITE(handle->conn)) {
errno = EPERM;
return -1;
}

rv = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, EMPTY_XATTR,
sizeof(EMPTY_XATTR), XATTR_CREATE);

if ((rv == -1) && as_root && ((errno == EPERM) || (errno == EACCES))) {
become_root();
rv = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, EMPTY_XATTR,
sizeof(EMPTY_XATTR), XATTR_CREATE);
unbecome_root();
}

if (rv == -1) {
DBG_INFO("%s: failed to seed builtin xattr on [%s]: %s\n",
name, fsp_str_dbg(fsp), strerror(errno));
}

return rv;
}

static ssize_t parse_retrieved_xattr(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *name,
char *value,
ssize_t xattr_get_rv,
struct streams_xattr_config *config)
{
ssize_t rv = xattr_get_rv;

if (!is_builtin_attr_name(name, config)) {
return rv;
}

if (xattr_get_rv == -1) {
if ((errno == ENOATTR) && (config->seed_builtin_attrs)) {
seed_builtin_attr(handle, fsp, name, true);
}
} else if (xattr_get_rv == sizeof(EMPTY_XATTR)) {
size_t off;
bool has_data = false;

for (off=0; off < rv; off++) {
if (value[off] != '\0') {
has_data = true;
break;
}
}

if (!has_data) {
errno = ENOATTR;
rv = -1;
}
}

return rv;
}

static ssize_t streams_xattr_fgetxattr(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *name,
Expand All @@ -1395,13 +1501,19 @@ static ssize_t streams_xattr_fgetxattr(struct vfs_handle_struct *handle,
{
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
struct streams_xattr_config *config = NULL;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
return -1);

ssize_t rv = -1;

if (sio == NULL) {
return SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
rv = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
return parse_retrieved_xattr(handle, fsp, name, value, rv, config);
}

errno = ENOTSUP;
return -1;
return rv;
}

static ssize_t streams_xattr_flistxattr(struct vfs_handle_struct *handle,
Expand All @@ -1426,8 +1538,16 @@ static int streams_xattr_fremovexattr(struct vfs_handle_struct *handle,
{
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
struct streams_xattr_config *config = NULL;

SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
return -1);

if (sio == NULL) {
if (config->seed_builtin_attrs &&
is_builtin_attr_name(sio->xattr_name, config)) {
return seed_builtin_attr(handle, fsp, sio->xattr_name, false);
}
return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
}

Expand Down