summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2016-12-11 19:10:05 +0100
committerStefan Metzmacher <metze@samba.org>2017-03-07 08:28:15 +0100
commit39c71b82a4b85c27dcd9c1f558a356ae78529fdf (patch)
tree02a080d35f91ce9be365415a3c27b91cceb7fc35
parenta01b97637817e8aa85308caacb3927a0fce64ba2 (diff)
downloadsamba-39c71b82a4b85c27dcd9c1f558a356ae78529fdf.tar.gz
vfs_fruit: ignore or delete invalid AFP_AfpInfo streams
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12427 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Uri Simchoni <uri@samba.org> (cherry picked from commit a2afd61906fbf36f75b2054abfd7384f220a14e3)
-rw-r--r--source3/modules/vfs_fruit.c89
1 files changed, 88 insertions, 1 deletions
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 4a636ab40e8..6d6fb9f3b20 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -3512,7 +3512,26 @@ static ssize_t fruit_pread_meta_stream(vfs_handle_struct *handle,
files_struct *fsp, void *data,
size_t n, off_t offset)
{
- return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+ ssize_t nread;
+ int ret;
+
+ nread = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+
+ if (nread == n) {
+ return nread;
+ }
+
+ DBG_ERR("Removing [%s] after short read [%zd]\n",
+ fsp_str_dbg(fsp), nread);
+
+ ret = SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name);
+ if (ret != 0) {
+ DBG_ERR("Removing [%s] failed\n", fsp_str_dbg(fsp));
+ return -1;
+ }
+
+ errno = EINVAL;
+ return -1;
}
static ssize_t fruit_pread_meta_adouble(vfs_handle_struct *handle,
@@ -4350,6 +4369,50 @@ static NTSTATUS fruit_streaminfo_meta_stream(
unsigned int *pnum_streams,
struct stream_struct **pstreams)
{
+ struct stream_struct *stream = *pstreams;
+ unsigned int num_streams = *pnum_streams;
+ struct smb_filename *sname = NULL;
+ int i;
+ int ret;
+ bool ok;
+
+ for (i = 0; i < num_streams; i++) {
+ if (strequal_m(stream[i].name, AFPINFO_STREAM)) {
+ break;
+ }
+ }
+
+ if (i == num_streams) {
+ return NT_STATUS_OK;
+ }
+
+ if (stream[i].size == AFP_INFO_SIZE) {
+ return NT_STATUS_OK;
+ }
+
+ DBG_ERR("Removing invalid AFPINFO_STREAM size [%zd] from [%s]\n",
+ stream[i].size, smb_fname_str_dbg(smb_fname));
+
+ ok = del_fruit_stream(mem_ctx, pnum_streams, pstreams, AFPINFO_STREAM);
+ if (!ok) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ sname = synthetic_smb_fname(talloc_tos(),
+ smb_fname->base_name,
+ AFPINFO_STREAM_NAME,
+ NULL, 0);
+ if (sname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = SMB_VFS_NEXT_UNLINK(handle, sname);
+ TALLOC_FREE(sname);
+ if (ret != 0) {
+ DBG_ERR("Removing [%s] failed\n", smb_fname_str_dbg(sname));
+ return map_nt_error_from_unix(errno);
+ }
+
return NT_STATUS_OK;
}
@@ -4361,8 +4424,11 @@ static NTSTATUS fruit_streaminfo_meta_netatalk(
unsigned int *pnum_streams,
struct stream_struct **pstreams)
{
+ struct stream_struct *stream = *pstreams;
+ unsigned int num_streams = *pnum_streams;
struct adouble *ad = NULL;
bool is_fi_empty;
+ int i;
bool ok;
/* Remove the Netatalk xattr from the list */
@@ -4372,6 +4438,27 @@ static NTSTATUS fruit_streaminfo_meta_netatalk(
return NT_STATUS_NO_MEMORY;
}
+ /*
+ * Check if there's a AFPINFO_STREAM from the VFS streams
+ * backend and if yes, remove it from the list
+ */
+ for (i = 0; i < num_streams; i++) {
+ if (strequal_m(stream[i].name, AFPINFO_STREAM)) {
+ break;
+ }
+ }
+
+ if (i < num_streams) {
+ DBG_WARNING("Unexpected AFPINFO_STREAM on [%s]\n",
+ smb_fname_str_dbg(smb_fname));
+
+ ok = del_fruit_stream(mem_ctx, pnum_streams, pstreams,
+ AFPINFO_STREAM);
+ if (!ok) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
ad = ad_get(talloc_tos(), handle,
smb_fname->base_name, ADOUBLE_META);
if (ad == NULL) {