VFS: Add initial implemenataion for SMB_VFS_FCHFLAGS
authorNoel Power <noel.power@suse.com>
Thu, 10 Jun 2021 15:31:40 +0000 (16:31 +0100)
committerNoel Power <npower@samba.org>
Tue, 29 Jun 2021 08:21:37 +0000 (08:21 +0000)
Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_not_implemented.c
source3/modules/vfs_time_audit.c
source3/smbd/vfs.c
source3/wscript

index 2fad722de04dd63d28fd52775733155041d9a677..44bc5687543fed7174fda2e898fcaa377cae5428 100644 (file)
@@ -514,6 +514,14 @@ static int skel_chflags(vfs_handle_struct *handle,
        return -1;
 }
 
+static int skel_fchflags(vfs_handle_struct *handle,
+                       struct files_struct *fsp,
+                       uint flags)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 static struct file_id skel_file_id_create(vfs_handle_struct *handle,
                                          const SMB_STRUCT_STAT *sbuf)
 {
@@ -1029,6 +1037,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
        .mknodat_fn = skel_mknodat,
        .realpath_fn = skel_realpath,
        .chflags_fn = skel_chflags,
+       .fchflags_fn = skel_fchflags,
        .file_id_create_fn = skel_file_id_create,
        .fs_file_id_fn = skel_fs_file_id,
        .offload_read_send_fn = skel_offload_read_send,
index 6783996a5e0eb695c353711546724328366ae5c8..fd7aac4d6a750dc0efe70ebec87a57d9556ef536 100644 (file)
@@ -649,6 +649,13 @@ static int skel_chflags(vfs_handle_struct *handle,
        return SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
 }
 
+static int skel_fchflags(vfs_handle_struct *handle,
+                       struct files_struct *fsp,
+                       uint flags)
+{
+       return SMB_VFS_NEXT_FCHFLAGS(handle, fsp, flags);
+}
+
 static struct file_id skel_file_id_create(vfs_handle_struct *handle,
                                          const SMB_STRUCT_STAT *sbuf)
 {
@@ -1334,6 +1341,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
        .mknodat_fn = skel_mknodat,
        .realpath_fn = skel_realpath,
        .chflags_fn = skel_chflags,
+       .fchflags_fn = skel_fchflags,
        .file_id_create_fn = skel_file_id_create,
        .fs_file_id_fn = skel_fs_file_id,
        .offload_read_send_fn = skel_offload_read_send,
index 5bc9f18ad57ef05bcfd84412f3400b5e54ea7bf3..012a47e7ff7f44dda5fddf3f95418422a04a1984 100644 (file)
  * Version 45 - Remove SMB_VFS_GET_NT_ACL_AT
  * Version 45 - Remove SYS_ACL_GET_FILE
  * Version 45 - Remove SYS_ACL_BLOB_GET_FILE
+ * Version 45 - Add SMB_VFS_FCHFLAGS
  */
 
 #define SMB_VFS_INTERFACE_VERSION 45
@@ -1069,6 +1070,9 @@ struct vfs_fn_pointers {
        int (*chflags_fn)(struct vfs_handle_struct *handle,
                                const struct smb_filename *smb_fname,
                                unsigned int flags);
+       int (*fchflags_fn)(struct vfs_handle_struct *handle,
+                               struct files_struct *fsp,
+                               unsigned int flags);
        struct file_id (*file_id_create_fn)(struct vfs_handle_struct *handle,
                                            const SMB_STRUCT_STAT *sbuf);
        uint64_t (*fs_file_id_fn)(struct vfs_handle_struct *handle,
@@ -1582,6 +1586,9 @@ struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        unsigned int flags);
+int smb_vfs_call_fchflags(struct vfs_handle_struct *handle,
+                       struct files_struct *fsp,
+                       unsigned int flags);
 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
                                           const SMB_STRUCT_STAT *sbuf);
 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
@@ -2005,6 +2012,9 @@ struct smb_filename *vfs_not_implemented_realpath(vfs_handle_struct *handle,
 int vfs_not_implemented_chflags(vfs_handle_struct *handle,
                                const struct smb_filename *smb_fname,
                                uint flags);
+int vfs_not_implemented_fchflags(vfs_handle_struct *handle,
+                               struct files_struct *fst,
+                               uint flags);
 struct file_id vfs_not_implemented_file_id_create(vfs_handle_struct *handle,
                                                  const SMB_STRUCT_STAT *sbuf);
 uint64_t vfs_not_implemented_fs_file_id(vfs_handle_struct *handle,
index 2d2aa206c2e0ca068debf232a735211ec70cb5b2..be594166f04e6bc8d8e26dcc620a411e466c2bcb 100644 (file)
 #define SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags) \
        smb_vfs_call_chflags((handle)->next, (smb_fname), (flags))
 
+#define SMB_VFS_FCHFLAGS(fsp, flags) \
+       smb_vfs_call_fchflags((fsp)->conn->vfs_handles, (fsp), (flags))
+#define SMB_VFS_NEXT_FCHFLAGS(handle, fsp, flags) \
+       smb_vfs_call_fchflags((handle)->next, (fsp), (flags))
+
 #define SMB_VFS_FILE_ID_CREATE(conn, sbuf) \
        smb_vfs_call_file_id_create((conn)->vfs_handles, (sbuf))
 #define SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf) \
index 9acc5bda0ad8770bee3d380f7cce7f2967942688..f1f84aeaa35d3fd8a0fbbffb68cb5b84323b9261 100644 (file)
@@ -3077,6 +3077,39 @@ static int vfswrap_chflags(vfs_handle_struct *handle,
 #endif
 }
 
+static int vfswrap_fchflags(vfs_handle_struct *handle,
+                       struct files_struct *fsp,
+                       unsigned int flags)
+{
+#ifdef HAVE_FCHFLAGS
+       int fd = fsp_get_pathref_fd(fsp);
+
+       if (!fsp->fsp_flags.is_pathref) {
+               return fchflags(fd, flags);
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p == NULL) {
+                       return -1;
+               }
+
+               return chflags(p, flags);
+       }
+
+       /*
+        * This is no longer a handle based call.
+        */
+       return chflags(fsp->fsp_name->base_name, flags);
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
                                             const SMB_STRUCT_STAT *sbuf)
 {
@@ -3848,6 +3881,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .mknodat_fn = vfswrap_mknodat,
        .realpath_fn = vfswrap_realpath,
        .chflags_fn = vfswrap_chflags,
+       .fchflags_fn = vfswrap_fchflags,
        .file_id_create_fn = vfswrap_file_id_create,
        .fs_file_id_fn = vfswrap_fs_file_id,
        .fstreaminfo_fn = vfswrap_fstreaminfo,
index bac60117eeafc08c43ccbf9c1f8541cf1606bd95..d9c387a89631911d85602938b5c8238200c7f121 100644 (file)
@@ -161,6 +161,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_MKNODAT,
        SMB_VFS_OP_REALPATH,
        SMB_VFS_OP_CHFLAGS,
+       SMB_VFS_OP_FCHFLAGS,
        SMB_VFS_OP_FILE_ID_CREATE,
        SMB_VFS_OP_FS_FILE_ID,
        SMB_VFS_OP_FSTREAMINFO,
@@ -298,6 +299,7 @@ static struct {
        { SMB_VFS_OP_MKNODAT,   "mknodat" },
        { SMB_VFS_OP_REALPATH,  "realpath" },
        { SMB_VFS_OP_CHFLAGS,   "chflags" },
+       { SMB_VFS_OP_FCHFLAGS,  "fchflags" },
        { SMB_VFS_OP_FILE_ID_CREATE,    "file_id_create" },
        { SMB_VFS_OP_FS_FILE_ID,        "fs_file_id" },
        { SMB_VFS_OP_FSTREAMINFO,       "fstreaminfo" },
@@ -1998,6 +2000,23 @@ static int smb_full_audit_chflags(vfs_handle_struct *handle,
        return result;
 }
 
+static int smb_full_audit_fchflags(vfs_handle_struct *handle,
+                       struct files_struct *fsp,
+                       unsigned int flags)
+{
+       int result;
+
+       result = SMB_VFS_NEXT_FCHFLAGS(handle, fsp, flags);
+
+       do_log(SMB_VFS_OP_FCHFLAGS,
+              (result != 0),
+              handle,
+              "%s",
+              smb_fname_str_do_log(handle->conn, fsp->fsp_name));
+
+       return result;
+}
+
 static struct file_id smb_full_audit_file_id_create(struct vfs_handle_struct *handle,
                                                    const SMB_STRUCT_STAT *sbuf)
 {
@@ -2959,6 +2978,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
        .mknodat_fn = smb_full_audit_mknodat,
        .realpath_fn = smb_full_audit_realpath,
        .chflags_fn = smb_full_audit_chflags,
+       .fchflags_fn = smb_full_audit_fchflags,
        .file_id_create_fn = smb_full_audit_file_id_create,
        .fs_file_id_fn = smb_full_audit_fs_file_id,
        .offload_read_send_fn = smb_full_audit_offload_read_send,
index 2dfac2338c6e4904fc4548bc9a4be5913217426f..e616a56b017398c78433ac56793d5677b3fcff0c 100644 (file)
@@ -512,6 +512,14 @@ int vfs_not_implemented_chflags(vfs_handle_struct *handle,
        return -1;
 }
 
+int vfs_not_implemented_fchflags(vfs_handle_struct *handle,
+                               struct files_struct *fsp,
+                               uint flags)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 struct file_id vfs_not_implemented_file_id_create(vfs_handle_struct *handle,
                                                  const SMB_STRUCT_STAT *sbuf)
 {
@@ -1033,6 +1041,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
        .mknodat_fn = vfs_not_implemented_mknodat,
        .realpath_fn = vfs_not_implemented_realpath,
        .chflags_fn = vfs_not_implemented_chflags,
+       .fchflags_fn = vfs_not_implemented_fchflags,
        .file_id_create_fn = vfs_not_implemented_file_id_create,
        .fs_file_id_fn = vfs_not_implemented_fs_file_id,
        .offload_read_send_fn = vfs_not_implemented_offload_read_send,
index 2f198c3c9673a10441007fdcd9755a87ef30a371..efc9133250a459f6b4786c02c2cd55990d4ff107 100644 (file)
@@ -1615,6 +1615,28 @@ static int smb_time_audit_chflags(vfs_handle_struct *handle,
        return result;
 }
 
+static int smb_time_audit_fchflags(vfs_handle_struct *handle,
+                               struct files_struct *fsp,
+                               unsigned int flags)
+{
+       int result;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       clock_gettime_mono(&ts1);
+       result = SMB_VFS_NEXT_FCHFLAGS(handle, fsp, flags);
+       clock_gettime_mono(&ts2);
+       timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
+
+       if (timediff > audit_timeout) {
+               smb_time_audit_log_smb_fname("chflags",
+                                            timediff,
+                                            fsp->fsp_name);
+       }
+
+       return result;
+}
+
 static struct file_id smb_time_audit_file_id_create(struct vfs_handle_struct *handle,
                                                    const SMB_STRUCT_STAT *sbuf)
 {
@@ -2766,6 +2788,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
        .mknodat_fn = smb_time_audit_mknodat,
        .realpath_fn = smb_time_audit_realpath,
        .chflags_fn = smb_time_audit_chflags,
+       .fchflags_fn = smb_time_audit_fchflags,
        .file_id_create_fn = smb_time_audit_file_id_create,
        .fs_file_id_fn = smb_time_audit_fs_file_id,
        .offload_read_send_fn = smb_time_audit_offload_read_send,
index a241fbbb9d2dd2a55cdccf497f8b96cc0d1d7782..8a9a858400f3d1168890a13c32f2fab2325c7177 100644 (file)
@@ -2386,6 +2386,14 @@ int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
        return handle->fns->chflags_fn(handle, smb_fname, flags);
 }
 
+int smb_vfs_call_fchflags(struct vfs_handle_struct *handle,
+                       struct files_struct *fsp,
+                       unsigned int flags)
+{
+       VFS_FIND(fchflags);
+       return handle->fns->fchflags_fn(handle, fsp, flags);
+}
+
 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
                                           const SMB_STRUCT_STAT *sbuf)
 {
index 56e594b59b78d0712d362243b3c7ece353c2cc47..c7434fedb92856cd2a1afdb4c9a0df1ed7ccafb1 100644 (file)
@@ -124,7 +124,7 @@ def configure(conf):
     conf.CHECK_HEADERS('linux/falloc.h linux/ioctl.h')
 
     conf.CHECK_FUNCS('getcwd fchown chmod fchmod mknod mknodat')
-    conf.CHECK_FUNCS('strtol strchr strupr chflags')
+    conf.CHECK_FUNCS('strtol strchr strupr chflags fchflags')
     conf.CHECK_FUNCS('getrlimit fsync setpgid')
     conf.CHECK_FUNCS('setsid glob strpbrk crypt16 getauthuid')
     conf.CHECK_FUNCS('innetgr')
@@ -384,6 +384,7 @@ int main(int argc, char **argv) {
 DNSServiceRegister
 atexit
 chflags
+fchflags
 chmod
 crypt16
 devnm