X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_vnops.c;h=00534d845ca6cd9e8ad8ee5f4373cd8ed9c54c39;hb=0d3ac5e7356d29fbb7d2880c0a0c457656355ca0;hp=2dcbfe00d6558c6cfb6db776dca0a91609bbf710;hpb=5484965ab650a56871a62a3373859a7a36ddafcb;p=zfs.git diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 2dcbfe0..00534d8 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -163,6 +163,76 @@ * return (error); // done, report error */ +/* + * Virus scanning is unsupported. It would be possible to add a hook + * here to performance the required virus scan. This could be done + * entirely in the kernel or potentially as an update to invoke a + * scanning utility. + */ +static int +zfs_vscan(struct inode *ip, cred_t *cr, int async) +{ + return (0); +} + +/* ARGSUSED */ +int +zfs_open(struct inode *ip, int mode, int flag, cred_t *cr) +{ + znode_t *zp = ITOZ(ip); + zfs_sb_t *zsb = ITOZSB(ip); + + ZFS_ENTER(zsb); + ZFS_VERIFY_ZP(zp); + + /* Honor ZFS_APPENDONLY file attribute */ + if ((mode & FMODE_WRITE) && (zp->z_pflags & ZFS_APPENDONLY) && + ((flag & O_APPEND) == 0)) { + ZFS_EXIT(zsb); + return (EPERM); + } + + /* Virus scan eligible files on open */ + if (!zfs_has_ctldir(zp) && zsb->z_vscan && S_ISREG(ip->i_mode) && + !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0) { + if (zfs_vscan(ip, cr, 0) != 0) { + ZFS_EXIT(zsb); + return (EACCES); + } + } + + /* Keep a count of the synchronous opens in the znode */ + if (flag & O_SYNC) + atomic_inc_32(&zp->z_sync_cnt); + + ZFS_EXIT(zsb); + return (0); +} +EXPORT_SYMBOL(zfs_open); + +/* ARGSUSED */ +int +zfs_close(struct inode *ip, int flag, cred_t *cr) +{ + znode_t *zp = ITOZ(ip); + zfs_sb_t *zsb = ITOZSB(ip); + + ZFS_ENTER(zsb); + ZFS_VERIFY_ZP(zp); + + /* Decrement the synchronous opens in the znode */ + if (flag & O_SYNC) + zp->z_sync_cnt = 0; + + if (!zfs_has_ctldir(zp) && zsb->z_vscan && S_ISREG(ip->i_mode) && + !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0) + VERIFY(zfs_vscan(ip, cr, 1) == 0); + + ZFS_EXIT(zsb); + return (0); +} +EXPORT_SYMBOL(zfs_close); + #if defined(_KERNEL) /* * When a file is memory mapped, we must keep the IO data synchronized @@ -2084,7 +2154,7 @@ zfs_getattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) mutex_enter(&zp->z_lock); vap->va_type = vn_mode_to_vtype(zp->z_mode); vap->va_mode = zp->z_mode; - vap->va_fsid = 0; + vap->va_fsid = ZTOI(zp)->i_sb->s_dev; vap->va_nodeid = zp->z_id; if ((zp->z_id == zsb->z_root) && zfs_show_ctldir(zp)) links = zp->z_links + 1; @@ -2248,7 +2318,7 @@ zfs_setattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) zilog_t *zilog; dmu_tx_t *tx; vattr_t oldva; - xvattr_t tmpxvattr; + xvattr_t *tmpxvattr; uint_t mask = vap->va_mask; uint_t saved_mask; int trim_mask = 0; @@ -2265,7 +2335,7 @@ zfs_setattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) zfs_acl_t *aclp; boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; boolean_t fuid_dirtied = B_FALSE; - sa_bulk_attr_t bulk[7], xattr_bulk[7]; + sa_bulk_attr_t *bulk, *xattr_bulk; int count = 0, xattr_count = 0; if (mask == 0) @@ -2305,7 +2375,11 @@ zfs_setattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) */ xoap = xva_getxoptattr(xvap); - xva_init(&tmpxvattr); + tmpxvattr = kmem_alloc(sizeof(xvattr_t), KM_SLEEP); + xva_init(tmpxvattr); + + bulk = kmem_alloc(sizeof(sa_bulk_attr_t) * 7, KM_SLEEP); + xattr_bulk = kmem_alloc(sizeof(sa_bulk_attr_t) * 7, KM_SLEEP); /* * Immutable files can only alter immutable bit and atime @@ -2313,13 +2387,13 @@ zfs_setattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) if ((zp->z_pflags & ZFS_IMMUTABLE) && ((mask & (ATTR_SIZE|ATTR_UID|ATTR_GID|ATTR_MTIME|ATTR_MODE)) || ((mask & ATTR_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME)))) { - ZFS_EXIT(zsb); - return (EPERM); + err = EPERM; + goto out3; } if ((mask & ATTR_SIZE) && (zp->z_pflags & ZFS_READONLY)) { - ZFS_EXIT(zsb); - return (EPERM); + err = EPERM; + goto out3; } /* @@ -2331,8 +2405,8 @@ zfs_setattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) if (mask & (ATTR_ATIME | ATTR_MTIME)) { if (((mask & ATTR_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) || ((mask & ATTR_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime))) { - ZFS_EXIT(zsb); - return (EOVERFLOW); + err = EOVERFLOW; + goto out3; } } @@ -2342,8 +2416,8 @@ top: /* Can this be moved to before the top label? */ if (zsb->z_vfs->mnt_flags & MNT_READONLY) { - ZFS_EXIT(zsb); - return (EROFS); + err = EROFS; + goto out3; } /* @@ -2352,10 +2426,9 @@ top: if (mask & ATTR_SIZE) { err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr); - if (err) { - ZFS_EXIT(zsb); - return (err); - } + if (err) + goto out3; + /* * XXX - Note, we are not providing any open * mode flags here (like FNDELAY), so we may @@ -2364,17 +2437,13 @@ top: */ /* XXX - would it be OK to generate a log record here? */ err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); - if (err) { - ZFS_EXIT(zsb); - return (err); - } + if (err) + goto out3; /* Careful negative Linux return code here */ err = -vmtruncate(ip, vap->va_size); - if (err) { - ZFS_EXIT(zsb); - return (err); - } + if (err) + goto out3; } if (mask & (ATTR_ATIME|ATTR_MTIME) || @@ -2455,7 +2524,7 @@ top: need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_APPENDONLY); - XVA_SET_REQ(&tmpxvattr, XAT_APPENDONLY); + XVA_SET_REQ(tmpxvattr, XAT_APPENDONLY); } } @@ -2465,7 +2534,7 @@ top: need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_NOUNLINK); - XVA_SET_REQ(&tmpxvattr, XAT_NOUNLINK); + XVA_SET_REQ(tmpxvattr, XAT_NOUNLINK); } } @@ -2475,7 +2544,7 @@ top: need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_IMMUTABLE); - XVA_SET_REQ(&tmpxvattr, XAT_IMMUTABLE); + XVA_SET_REQ(tmpxvattr, XAT_IMMUTABLE); } } @@ -2485,7 +2554,7 @@ top: need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_NODUMP); - XVA_SET_REQ(&tmpxvattr, XAT_NODUMP); + XVA_SET_REQ(tmpxvattr, XAT_NODUMP); } } @@ -2495,7 +2564,7 @@ top: need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_AV_MODIFIED); - XVA_SET_REQ(&tmpxvattr, XAT_AV_MODIFIED); + XVA_SET_REQ(tmpxvattr, XAT_AV_MODIFIED); } } @@ -2507,14 +2576,14 @@ top: need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_AV_QUARANTINED); - XVA_SET_REQ(&tmpxvattr, XAT_AV_QUARANTINED); + XVA_SET_REQ(tmpxvattr, XAT_AV_QUARANTINED); } } if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { mutex_exit(&zp->z_lock); - ZFS_EXIT(zsb); - return (EPERM); + err = EPERM; + goto out3; } if (need_policy == FALSE && @@ -2530,10 +2599,9 @@ top: if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { err = secpolicy_setid_setsticky_clear(ip, vap, &oldva, cr); - if (err) { - ZFS_EXIT(zsb); - return (err); - } + if (err) + goto out3; + trim_mask |= ATTR_MODE; } else { need_policy = TRUE; @@ -2555,10 +2623,8 @@ top: } err = secpolicy_vnode_setattr(cr, ip, vap, &oldva, flags, (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp); - if (err) { - ZFS_EXIT(zsb); - return (err); - } + if (err) + goto out3; if (trim_mask) vap->va_mask |= saved_mask; @@ -2783,22 +2849,22 @@ top: * so that return masks can be set for caller. */ - if (XVA_ISSET_REQ(&tmpxvattr, XAT_APPENDONLY)) { + if (XVA_ISSET_REQ(tmpxvattr, XAT_APPENDONLY)) { XVA_SET_REQ(xvap, XAT_APPENDONLY); } - if (XVA_ISSET_REQ(&tmpxvattr, XAT_NOUNLINK)) { + if (XVA_ISSET_REQ(tmpxvattr, XAT_NOUNLINK)) { XVA_SET_REQ(xvap, XAT_NOUNLINK); } - if (XVA_ISSET_REQ(&tmpxvattr, XAT_IMMUTABLE)) { + if (XVA_ISSET_REQ(tmpxvattr, XAT_IMMUTABLE)) { XVA_SET_REQ(xvap, XAT_IMMUTABLE); } - if (XVA_ISSET_REQ(&tmpxvattr, XAT_NODUMP)) { + if (XVA_ISSET_REQ(tmpxvattr, XAT_NODUMP)) { XVA_SET_REQ(xvap, XAT_NODUMP); } - if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_MODIFIED)) { + if (XVA_ISSET_REQ(tmpxvattr, XAT_AV_MODIFIED)) { XVA_SET_REQ(xvap, XAT_AV_MODIFIED); } - if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_QUARANTINED)) { + if (XVA_ISSET_REQ(tmpxvattr, XAT_AV_QUARANTINED)) { XVA_SET_REQ(xvap, XAT_AV_QUARANTINED); } @@ -2854,6 +2920,10 @@ out2: if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); +out3: + kmem_free(xattr_bulk, sizeof(sa_bulk_attr_t) * 7); + kmem_free(bulk, sizeof(sa_bulk_attr_t) * 7); + kmem_free(tmpxvattr, sizeof(xvattr_t)); ZFS_EXIT(zsb); return (err); }