vscan_svc.c revision 53c110294d8b1410cabc201a52f94b03ae2ef448
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * CDDL HEADER START
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The contents of this file are subject to the terms of the
911106dfb16696472af8c1b7b4c554a829354fa8jm * Common Development and Distribution License (the "License").
911106dfb16696472af8c1b7b4c554a829354fa8jm * You may not use this file except in compliance with the License.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911106dfb16696472af8c1b7b4c554a829354fa8jm * or http://www.opensolaris.org/os/licensing.
911106dfb16696472af8c1b7b4c554a829354fa8jm * See the License for the specific language governing permissions
911106dfb16696472af8c1b7b4c554a829354fa8jm * and limitations under the License.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * When distributing Covered Code, include this CDDL HEADER in each
911106dfb16696472af8c1b7b4c554a829354fa8jm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
911106dfb16696472af8c1b7b4c554a829354fa8jm * If applicable, add the following below this CDDL HEADER, with the
911106dfb16696472af8c1b7b4c554a829354fa8jm * fields enclosed by brackets "[]" replaced with your own identifying
911106dfb16696472af8c1b7b4c554a829354fa8jm * information: Portions Copyright [yyyy] [name of copyright owner]
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * CDDL HEADER END
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
53c110294d8b1410cabc201a52f94b03ae2ef448jm * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Use is subject to license terms.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm#pragma ident "%Z%%M% %I% %E% SMI"
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/stat.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/ddi.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/sunddi.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/time.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/varargs.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/conf.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/modctl.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/cmn_err.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/vnode.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <fs/fs_subr.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/types.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/file.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/disp.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/sdt.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/cred.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/vscan.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm#define VS_TASKQ_NUM_THREADS VS_DRV_MAX_FILES
911106dfb16696472af8c1b7b4c554a829354fa8jm#define VS_EXT_RECURSE_DEPTH 8
911106dfb16696472af8c1b7b4c554a829354fa8jm#define tolower(C) (((C) >= 'A' && (C) <= 'Z') ? (C) - 'A' + 'a' : (C))
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* represents request received from filesystem - currently only use vp */
911106dfb16696472af8c1b7b4c554a829354fa8jmtypedef struct vscan_fs_req {
911106dfb16696472af8c1b7b4c554a829354fa8jm vnode_t *vsr_vp;
911106dfb16696472af8c1b7b4c554a829354fa8jm} vscan_fs_req_t;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_files - table of files being scanned
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The index into this table is passed in the door call to
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscand. vscand uses the idx to determine which minor node
911106dfb16696472af8c1b7b4c554a829354fa8jm * to open to read the file data. Within the kernel driver
911106dfb16696472af8c1b7b4c554a829354fa8jm * the minor device number can thus be used to identify the
911106dfb16696472af8c1b7b4c554a829354fa8jm * table index to get the appropriate vnode.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Instance 0 is reserved for the daemon/driver control
911106dfb16696472af8c1b7b4c554a829354fa8jm * interface: enable/configure/disable
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmtypedef struct vscan_file {
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_fs_req_t vsf_req;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint32_t vsf_wait_count;
53c110294d8b1410cabc201a52f94b03ae2ef448jm kcondvar_t vsf_cv; /* wait for in progress scan */
911106dfb16696472af8c1b7b4c554a829354fa8jm uint8_t vsf_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint8_t vsf_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint64_t vsf_size;
53c110294d8b1410cabc201a52f94b03ae2ef448jm timestruc_t vsf_mtime;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_scanstamp_t vsf_scanstamp;
53c110294d8b1410cabc201a52f94b03ae2ef448jm uint32_t vsf_result;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint32_t vsf_access;
911106dfb16696472af8c1b7b4c554a829354fa8jm} vscan_file_t;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic vscan_file_t vscan_svc_files[VS_DRV_MAX_FILES + 1];
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic kcondvar_t vscan_svc_cv; /* wait for slot in vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_wait_count = 0; /* # waiting for slot in vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_req_count = 0; /* # scan requests */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic taskq_t *vscan_svc_taskq = NULL;
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic boolean_t vscan_svc_enabled = B_FALSE;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_mutex protects the data pertaining to scan requests:
911106dfb16696472af8c1b7b4c554a829354fa8jm * file table - vscan_svc_files
911106dfb16696472af8c1b7b4c554a829354fa8jm * counts - vscan_svc_wait_count, vscan_svc_req_count
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic kmutex_t vscan_svc_mutex;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_cfg_mutex protects the configuration data:
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_config, vscan_svc_types
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic kmutex_t vscan_svc_cfg_mutex;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* configuration data - for virus scan exemption */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic vs_config_t vscan_svc_config;
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic char *vscan_svc_types[VS_TYPES_MAX];
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* local functions */
911106dfb16696472af8c1b7b4c554a829354fa8jmint vscan_svc_scan_file(vnode_t *, cred_t *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid vscan_svc_taskq_callback(void *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_exempt_file(vnode_t *, boolean_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_exempt_filetype(char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_match_ext(char *, char *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_do_scan(vscan_fs_req_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_wait_for_scan(vnode_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_insert_file(vscan_fs_req_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vscan_svc_release_file(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_find_slot(void);
53c110294d8b1410cabc201a52f94b03ae2ef448jmstatic void vscan_svc_process_scan_result(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vscan_svc_notify_scan_complete(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_getattr(int);
53c110294d8b1410cabc201a52f94b03ae2ef448jmstatic int vscan_svc_setattr(int, int);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic vs_scan_req_t *vscan_svc_populate_req(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vscan_svc_parse_rsp(int, vs_scan_req_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_init
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmint
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_init()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_init(&vscan_svc_mutex, NULL, MUTEX_DRIVER, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_init(&vscan_svc_cfg_mutex, NULL, MUTEX_DRIVER, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(&vscan_svc_files, 0, sizeof (vscan_svc_files));
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_init(&vscan_svc_cv, NULL, CV_DEFAULT, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_fini
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_fini()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vscan_svc_enabled == B_FALSE);
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vscan_svc_in_use() == B_FALSE);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_destroy(&vscan_svc_cv);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_destroy(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_destroy(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_enable
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
53c110294d8b1410cabc201a52f94b03ae2ef448jmvscan_svc_enable(void)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm mutex_enter(&vscan_svc_mutex);
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_svc_enabled = B_TRUE;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (vscan_svc_taskq == NULL) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm if ((vscan_svc_taskq = taskq_create("vscan",
53c110294d8b1410cabc201a52f94b03ae2ef448jm VS_TASKQ_NUM_THREADS, MINCLSYSPRI, 1,
53c110294d8b1410cabc201a52f94b03ae2ef448jm INT_MAX, TASKQ_DYNAMIC)) == NULL) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm cmn_err(CE_WARN, "All scan requests "
53c110294d8b1410cabc201a52f94b03ae2ef448jm "will be processed synchronously");
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm fs_vscan_register(vscan_svc_scan_file);
53c110294d8b1410cabc201a52f94b03ae2ef448jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm/*
53c110294d8b1410cabc201a52f94b03ae2ef448jm * vscan_svc_disable
53c110294d8b1410cabc201a52f94b03ae2ef448jm */
53c110294d8b1410cabc201a52f94b03ae2ef448jmvoid
53c110294d8b1410cabc201a52f94b03ae2ef448jmvscan_svc_disable(void)
53c110294d8b1410cabc201a52f94b03ae2ef448jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm mutex_enter(&vscan_svc_mutex);
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_svc_enabled = B_FALSE;
53c110294d8b1410cabc201a52f94b03ae2ef448jm fs_vscan_register(NULL);
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (vscan_svc_taskq) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm taskq_destroy(vscan_svc_taskq);
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_svc_taskq = NULL;
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
53c110294d8b1410cabc201a52f94b03ae2ef448jm mutex_exit(&vscan_svc_mutex);
53c110294d8b1410cabc201a52f94b03ae2ef448jm}
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm/*
53c110294d8b1410cabc201a52f94b03ae2ef448jm * vscan_svc_is_enabled
53c110294d8b1410cabc201a52f94b03ae2ef448jm */
53c110294d8b1410cabc201a52f94b03ae2ef448jmboolean_t
53c110294d8b1410cabc201a52f94b03ae2ef448jmvscan_svc_is_enabled()
53c110294d8b1410cabc201a52f94b03ae2ef448jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm return (vscan_svc_enabled);
53c110294d8b1410cabc201a52f94b03ae2ef448jm}
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_in_use
53c110294d8b1410cabc201a52f94b03ae2ef448jm *
53c110294d8b1410cabc201a52f94b03ae2ef448jm * The vscan driver is considered to be in use if it is
53c110294d8b1410cabc201a52f94b03ae2ef448jm * enabled or if there are in-progress scan requests.
53c110294d8b1410cabc201a52f94b03ae2ef448jm * Used to determine whether the driver can be unloaded.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmboolean_t
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_in_use()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm boolean_t rc;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
53c110294d8b1410cabc201a52f94b03ae2ef448jm rc = (vscan_svc_enabled == B_TRUE) || (vscan_svc_req_count > 0);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_get_vnode
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Get the file vnode indexed by idx.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns NULL if idx not valid.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvnode_t *
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_get_vnode(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(idx > 0);
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(idx <= VS_DRV_MAX_FILES);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((idx <= 0) || (idx > VS_DRV_MAX_FILES))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm else
911106dfb16696472af8c1b7b4c554a829354fa8jm return (vscan_svc_files[idx].vsf_req.vsr_vp);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_scan_file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * This function is the entry point for the file system to
911106dfb16696472af8c1b7b4c554a829354fa8jm * request that a file be virus scanned.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Asynchronous requests:
911106dfb16696472af8c1b7b4c554a829354fa8jm * If an async scan request cannot be queued it is discarded.
911106dfb16696472af8c1b7b4c554a829354fa8jm * By definition the caller of an async request is not dependent
911106dfb16696472af8c1b7b4c554a829354fa8jm * on the outcome of the result. Although the file will thus
911106dfb16696472af8c1b7b4c554a829354fa8jm * not be scanned at this time, it will be scanned
911106dfb16696472af8c1b7b4c554a829354fa8jm * (synchronously) on subsequent access.
911106dfb16696472af8c1b7b4c554a829354fa8jm * This scenario should not occur during normal operation.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Before queuing an async request do VN_HOLD(vp). VN_RELE(vp)
911106dfb16696472af8c1b7b4c554a829354fa8jm * will be done when the scan completes or if the request
911106dfb16696472af8c1b7b4c554a829354fa8jm * couldn't be queued.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The vscan_fs_req_t, allocated to hold the request information
911106dfb16696472af8c1b7b4c554a829354fa8jm * passed from the fs, will be free'd when the scan completes.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmint
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_scan_file(vnode_t *vp, cred_t *cr, int async)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int rc = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_fs_req_t *req;
911106dfb16696472af8c1b7b4c554a829354fa8jm boolean_t allow;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((vp == NULL) || (vp->v_path == NULL) || cr == NULL) {
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__scan__file, char *, vp->v_path, int, async);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* check if size or type exempts file from scanning */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_exempt_file(vp, &allow)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((allow == B_TRUE) || (async != 0))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (EACCES);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_req_count++;
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm req = kmem_zalloc(sizeof (vscan_fs_req_t), KM_SLEEP);
911106dfb16696472af8c1b7b4c554a829354fa8jm req->vsr_vp = vp;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (async) {
911106dfb16696472af8c1b7b4c554a829354fa8jm VN_HOLD(vp);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_taskq &&
911106dfb16696472af8c1b7b4c554a829354fa8jm taskq_dispatch(vscan_svc_taskq, vscan_svc_taskq_callback,
911106dfb16696472af8c1b7b4c554a829354fa8jm (void *)req, TQ_SLEEP)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm VN_RELE(vp);
911106dfb16696472af8c1b7b4c554a829354fa8jm kmem_free(req, sizeof (vscan_fs_req_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = vscan_svc_do_scan(req);
911106dfb16696472af8c1b7b4c554a829354fa8jm kmem_free(req, sizeof (vscan_fs_req_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_req_count--;
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_taskq_callback
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Callback function for async scan requests
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_taskq_callback(void *data)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_fs_req_t *req = (vscan_fs_req_t *)data;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) vscan_svc_do_scan(req);
911106dfb16696472af8c1b7b4c554a829354fa8jm VN_RELE(req->vsr_vp); /* VN_HOLD done before request queued */
911106dfb16696472af8c1b7b4c554a829354fa8jm kmem_free(req, sizeof (vscan_fs_req_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_req_count--;
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_do_scan
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Should never be called directly. Invoke via vscan_svc_scan_file()
911106dfb16696472af8c1b7b4c554a829354fa8jm * If scan is in progress wait for it to complete, otherwise
911106dfb16696472af8c1b7b4c554a829354fa8jm * initiate door call to scan the file.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_do_scan(vscan_fs_req_t *req)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm int rc = -1, idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_scan_req_t *scan_req;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /*
911106dfb16696472af8c1b7b4c554a829354fa8jm * if a scan is in progress on the files vscan_svc_wait_for_scan will
911106dfb16696472af8c1b7b4c554a829354fa8jm * wait for it to complete and return the idx of the scan request.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Otherwise it will return -1 and we will initiate a scan here.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
53c110294d8b1410cabc201a52f94b03ae2ef448jm if ((idx = vscan_svc_wait_for_scan(req->vsr_vp)) != -1) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* insert the scan request into vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jm idx = vscan_svc_insert_file(req);
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_enabled) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_getattr(idx) == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* valid scan_req ptr guaranteed */
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req = vscan_svc_populate_req(idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (vscan_drv_create_node(idx) == B_TRUE)
53c110294d8b1410cabc201a52f94b03ae2ef448jm rc = vscan_door_scan_file(scan_req);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (rc == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_parse_rsp(idx, scan_req);
911106dfb16696472af8c1b7b4c554a829354fa8jm kmem_free(scan_req, sizeof (vs_scan_req_t));
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm /* process scan result */
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_svc_process_scan_result(idx);
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE2(vscan__result, int,
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_result, int,
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access);
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
53c110294d8b1410cabc201a52f94b03ae2ef448jm /* if getattr fails: log error, deny access */
911106dfb16696472af8c1b7b4c554a829354fa8jm cmn_err(CE_WARN, "Can't access xattr for %s\n",
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_req.vsr_vp->v_path);
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_DENY;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if vscan not enabled (shutting down), allow ACCESS */
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_ALLOW;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* When a scan completes the result is saved in vscan_svc_files */
53c110294d8b1410cabc201a52f94b03ae2ef448jm rc = (svc_file->vsf_access == VS_ACCESS_ALLOW) ? 0 : EACCES;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* wake threads waiting for result, or for a slot in vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_notify_scan_complete(idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* remove the entry from vscan_svc_files if nobody else is waiting */
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_release_file(idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm/*
53c110294d8b1410cabc201a52f94b03ae2ef448jm * vscan_svc_process_scan_result
53c110294d8b1410cabc201a52f94b03ae2ef448jm *
53c110294d8b1410cabc201a52f94b03ae2ef448jm * Sets vsf_access and updates file attributes based on vsf_result,
53c110294d8b1410cabc201a52f94b03ae2ef448jm * as follows:
53c110294d8b1410cabc201a52f94b03ae2ef448jm *
53c110294d8b1410cabc201a52f94b03ae2ef448jm * VS_STATUS_INFECTED
53c110294d8b1410cabc201a52f94b03ae2ef448jm * deny access, set quarantine attribute, clear scanstamp
53c110294d8b1410cabc201a52f94b03ae2ef448jm * VS_STATUS_CLEAN
53c110294d8b1410cabc201a52f94b03ae2ef448jm * allow access, set scanstamp,
53c110294d8b1410cabc201a52f94b03ae2ef448jm * if file not modified since scan initiated, clear modified attribute
53c110294d8b1410cabc201a52f94b03ae2ef448jm * VS_STATUS_NO_SCAN
53c110294d8b1410cabc201a52f94b03ae2ef448jm * deny access if file quarantined, otherwise allow access
53c110294d8b1410cabc201a52f94b03ae2ef448jm * VS_STATUS_UNDEFINED, VS_STATUS_ERROR
53c110294d8b1410cabc201a52f94b03ae2ef448jm * deny access if file quarantined, modified or no scanstamp
53c110294d8b1410cabc201a52f94b03ae2ef448jm * otherwise, allow access
53c110294d8b1410cabc201a52f94b03ae2ef448jm */
53c110294d8b1410cabc201a52f94b03ae2ef448jmstatic void
53c110294d8b1410cabc201a52f94b03ae2ef448jmvscan_svc_process_scan_result(int idx)
53c110294d8b1410cabc201a52f94b03ae2ef448jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm struct vattr attr;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vnode_t *vp;
53c110294d8b1410cabc201a52f94b03ae2ef448jm timestruc_t *mtime;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm switch (svc_file->vsf_result) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm case VS_STATUS_INFECTED:
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_DENY;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_quarantined = 1;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_scanstamp[0] = '\0';
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) vscan_svc_setattr(idx,
53c110294d8b1410cabc201a52f94b03ae2ef448jm XAT_AV_QUARANTINED | XAT_AV_SCANSTAMP);
53c110294d8b1410cabc201a52f94b03ae2ef448jm return;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm case VS_STATUS_CLEAN:
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_ALLOW;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm /* if mtime has changed, don't clear the modified attribute */
53c110294d8b1410cabc201a52f94b03ae2ef448jm vp = svc_file->vsf_req.vsr_vp;
53c110294d8b1410cabc201a52f94b03ae2ef448jm mtime = &(svc_file->vsf_mtime);
53c110294d8b1410cabc201a52f94b03ae2ef448jm attr.va_mask = AT_MTIME;
53c110294d8b1410cabc201a52f94b03ae2ef448jm if ((VOP_GETATTR(vp, &attr, 0, kcred, NULL) != 0) ||
53c110294d8b1410cabc201a52f94b03ae2ef448jm (mtime->tv_sec != attr.va_mtime.tv_sec) ||
53c110294d8b1410cabc201a52f94b03ae2ef448jm (mtime->tv_nsec != attr.va_mtime.tv_nsec)) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE1(vscan__mtime__changed, vscan_file_t *,
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file);
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) vscan_svc_setattr(idx, XAT_AV_SCANSTAMP);
53c110294d8b1410cabc201a52f94b03ae2ef448jm return;
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_modified = 0;
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) vscan_svc_setattr(idx,
53c110294d8b1410cabc201a52f94b03ae2ef448jm XAT_AV_SCANSTAMP | XAT_AV_MODIFIED);
53c110294d8b1410cabc201a52f94b03ae2ef448jm return;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm case VS_STATUS_NO_SCAN:
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (svc_file->vsf_quarantined)
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_DENY;
53c110294d8b1410cabc201a52f94b03ae2ef448jm else
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_ALLOW;
53c110294d8b1410cabc201a52f94b03ae2ef448jm return;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm case VS_STATUS_ERROR:
53c110294d8b1410cabc201a52f94b03ae2ef448jm case VS_STATUS_UNDEFINED:
53c110294d8b1410cabc201a52f94b03ae2ef448jm default:
53c110294d8b1410cabc201a52f94b03ae2ef448jm if ((svc_file->vsf_quarantined) ||
53c110294d8b1410cabc201a52f94b03ae2ef448jm (svc_file->vsf_modified) ||
53c110294d8b1410cabc201a52f94b03ae2ef448jm (svc_file->vsf_scanstamp[0] == '\0'))
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_DENY;
53c110294d8b1410cabc201a52f94b03ae2ef448jm else
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_ALLOW;
53c110294d8b1410cabc201a52f94b03ae2ef448jm return;
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
53c110294d8b1410cabc201a52f94b03ae2ef448jm}
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_wait_for_scan
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Search for vp in vscan_svc_files. If vp already exists in
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_files scan is already in progress on file so wait
911106dfb16696472af8c1b7b4c554a829354fa8jm * for the inprogress scan to complete.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: idx of file waited for
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 if file not already scanning
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_wait_for_scan(vnode_t *vp)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int idx;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vp);
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (idx = 1; idx <= VS_DRV_MAX_FILES; idx++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_files[idx].vsf_req.vsr_vp == vp)
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* file not found in table thus not currently being scanned */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (idx > VS_DRV_MAX_FILES)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* file found - wait for scan to complete */
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_wait_count++;
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE2(vscan__wait__scan, vscan_file_t *, svc_file, int, idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm while (svc_file->vsf_access == VS_ACCESS_UNDEFINED)
53c110294d8b1410cabc201a52f94b03ae2ef448jm cv_wait(&(svc_file->vsf_cv), &vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_wait_count--;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_find_slot
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Find empty slot in vscan_svc_files table.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns idx of slot, or -1 if not found
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_find_slot(void)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm int idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
53c110294d8b1410cabc201a52f94b03ae2ef448jm for (idx = 1; idx <= VS_DRV_MAX_FILES; idx++) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (vscan_svc_files[idx].vsf_req.vsr_vp == NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_insert_file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Find the next available flot in vscan_svc_files and
911106dfb16696472af8c1b7b4c554a829354fa8jm * initialize it for the scan request. If no slot is
911106dfb16696472af8c1b7b4c554a829354fa8jm * available, vscan_svc_find_slot will wait for one.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: idx of scan request in vscan_svc_files table
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_insert_file(vscan_fs_req_t *req)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int idx;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while ((idx = vscan_svc_find_slot()) == -1) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE1(vscan__wait__slot, char *, req->vsr_vp->v_path);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_wait_count++;
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_wait(&(vscan_svc_cv), &vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_wait_count--;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) memset(svc_file, 0, sizeof (vscan_file_t));
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_req = *req;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_modified = 1;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_result = VS_STATUS_UNDEFINED;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_access = VS_ACCESS_UNDEFINED;
53c110294d8b1410cabc201a52f94b03ae2ef448jm cv_init(&(svc_file->vsf_cv), NULL, CV_DEFAULT, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__insert, char *, req->vsr_vp->v_path, int, idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_release_file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Release the file (free the slot in vscan_svc_files)
911106dfb16696472af8c1b7b4c554a829354fa8jm * if no thread is waiting on it.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_release_file(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (svc_file->vsf_wait_count != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return;
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE2(vscan__release, char *,
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_req.vsr_vp->v_path, int, idx);
53c110294d8b1410cabc201a52f94b03ae2ef448jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm cv_destroy(&(svc_file->vsf_cv));
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) memset(svc_file, 0, sizeof (vscan_file_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_populate_req
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Allocate a scan request to be sent to vscand, populating it
911106dfb16696472af8c1b7b4c554a829354fa8jm * from the data in vscan_svc_files[idx].
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: scan request object
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic vs_scan_req_t *
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_populate_req(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_scan_req_t *scan_req;
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_fs_req_t *req;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm req = &(svc_file->vsf_req);
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req = kmem_zalloc(sizeof (vs_scan_req_t), KM_SLEEP);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_id = idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strncpy(scan_req->vsr_path, req->vsr_vp->v_path, MAXPATHLEN);
53c110294d8b1410cabc201a52f94b03ae2ef448jm scan_req->vsr_size = svc_file->vsf_size;
53c110294d8b1410cabc201a52f94b03ae2ef448jm scan_req->vsr_modified = svc_file->vsf_modified;
53c110294d8b1410cabc201a52f94b03ae2ef448jm scan_req->vsr_quarantined = svc_file->vsf_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_flags = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strncpy(scan_req->vsr_scanstamp,
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_scanstamp, sizeof (vs_scanstamp_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (scan_req);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_parse_rsp
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Parse scan response data and save in vscan_svc_files[idx]
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_parse_rsp(int idx, vs_scan_req_t *scan_req)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_result = scan_req->vsr_result;
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) strncpy(svc_file->vsf_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_scanstamp, sizeof (vs_scanstamp_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_notify_scan_complete
911106dfb16696472af8c1b7b4c554a829354fa8jm *
53c110294d8b1410cabc201a52f94b03ae2ef448jm * signal vscan_svc_files.vsf_cv and vscan_svc_cv to wake
53c110294d8b1410cabc201a52f94b03ae2ef448jm * threads waiting for the scan result for the specified
53c110294d8b1410cabc201a52f94b03ae2ef448jm * file (vscan_svc_files[idx].vsf_cv) or for a slot in
53c110294d8b1410cabc201a52f94b03ae2ef448jm * vscan_svc_files table (vscan_svc_cv)
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_notify_scan_complete(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if someone waiting for result, cv_signal */
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (svc_file->vsf_wait_count > 0)
53c110294d8b1410cabc201a52f94b03ae2ef448jm cv_signal(&(svc_file->vsf_cv));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* signal vscan_svc_cv if any threads waiting for a slot */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_wait_count > 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_signal(&vscan_svc_cv);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_getattr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
53c110294d8b1410cabc201a52f94b03ae2ef448jm * Get the vscan related system attributes, AT_SIZE & AT_MTIME.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_getattr(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm xvattr_t xvattr;
911106dfb16696472af8c1b7b4c554a829354fa8jm xoptattr_t *xoap = NULL;
911106dfb16696472af8c1b7b4c554a829354fa8jm vnode_t *vp;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm if ((vp = svc_file->vsf_req.vsr_vp) == NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* get the attributes */
911106dfb16696472af8c1b7b4c554a829354fa8jm xva_init(&xvattr); /* sets AT_XVATTR */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm xvattr.xva_vattr.va_mask |= AT_SIZE;
53c110294d8b1410cabc201a52f94b03ae2ef448jm xvattr.xva_vattr.va_mask |= AT_MTIME;
911106dfb16696472af8c1b7b4c554a829354fa8jm XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED);
911106dfb16696472af8c1b7b4c554a829354fa8jm XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED);
911106dfb16696472af8c1b7b4c554a829354fa8jm XVA_SET_REQ(&xvattr, XAT_AV_SCANSTAMP);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (VOP_GETATTR(vp, (vattr_t *)&xvattr, 0, kcred, NULL) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((xoap = xva_getxoptattr(&xvattr)) == NULL) {
911106dfb16696472af8c1b7b4c554a829354fa8jm cmn_err(CE_NOTE, "Virus scan request failed; "
911106dfb16696472af8c1b7b4c554a829354fa8jm "file system does not support virus scanning");
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_size = xvattr.xva_vattr.va_size;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_mtime.tv_sec = xvattr.xva_vattr.va_mtime.tv_sec;
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_mtime.tv_nsec = xvattr.xva_vattr.va_mtime.tv_nsec;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (XVA_ISSET_RTN(&xvattr, XAT_AV_MODIFIED) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_modified = xoap->xoa_av_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (XVA_ISSET_RTN(&xvattr, XAT_AV_QUARANTINED) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_quarantined = xoap->xoa_av_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (XVA_ISSET_RTN(&xvattr, XAT_AV_SCANSTAMP) != 0) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) memcpy(svc_file->vsf_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE1(vscan__getattr, vscan_file_t *, svc_file);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_setattr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Set the vscan related system attributes.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
53c110294d8b1410cabc201a52f94b03ae2ef448jmvscan_svc_setattr(int idx, int which)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm xvattr_t xvattr;
911106dfb16696472af8c1b7b4c554a829354fa8jm xoptattr_t *xoap = NULL;
911106dfb16696472af8c1b7b4c554a829354fa8jm vnode_t *vp;
911106dfb16696472af8c1b7b4c554a829354fa8jm int len;
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *svc_file;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file = &vscan_svc_files[idx];
53c110294d8b1410cabc201a52f94b03ae2ef448jm if ((vp = svc_file->vsf_req.vsr_vp) == NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* update the attributes */
911106dfb16696472af8c1b7b4c554a829354fa8jm xva_init(&xvattr); /* sets AT_XVATTR */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((xoap = xva_getxoptattr(&xvattr)) == NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (which & XAT_AV_MODIFIED) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED);
53c110294d8b1410cabc201a52f94b03ae2ef448jm xoap->xoa_av_modified = svc_file->vsf_modified;
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (which & XAT_AV_QUARANTINED) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED);
53c110294d8b1410cabc201a52f94b03ae2ef448jm xoap->xoa_av_quarantined = svc_file->vsf_quarantined;
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (which & XAT_AV_SCANSTAMP) {
53c110294d8b1410cabc201a52f94b03ae2ef448jm XVA_SET_REQ(&xvattr, XAT_AV_SCANSTAMP);
53c110294d8b1410cabc201a52f94b03ae2ef448jm len = strlen(svc_file->vsf_scanstamp);
53c110294d8b1410cabc201a52f94b03ae2ef448jm (void) memcpy(xoap->xoa_av_scanstamp,
53c110294d8b1410cabc201a52f94b03ae2ef448jm svc_file->vsf_scanstamp, len);
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if access is denied, set mtime to invalidate client cache */
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (svc_file->vsf_access != VS_ACCESS_ALLOW) {
911106dfb16696472af8c1b7b4c554a829354fa8jm xvattr.xva_vattr.va_mask |= AT_MTIME;
911106dfb16696472af8c1b7b4c554a829354fa8jm gethrestime(&xvattr.xva_vattr.va_mtime);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (VOP_SETATTR(vp, (vattr_t *)&xvattr, 0, kcred, NULL) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm DTRACE_PROBE2(vscan__setattr,
53c110294d8b1410cabc201a52f94b03ae2ef448jm vscan_file_t *, svc_file, int, which);
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_configure
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * store configuration in vscan_svc_config
911106dfb16696472af8c1b7b4c554a829354fa8jm * set up vscan_svc_types array of pointers into
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_config.vsc_types for efficient searching
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmint
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_configure(vs_config_t *conf)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int count = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *p, *beg, *end;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_config = *conf;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(vscan_svc_types, 0, sizeof (vscan_svc_types));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm beg = vscan_svc_config.vsc_types;
911106dfb16696472af8c1b7b4c554a829354fa8jm end = beg + vscan_svc_config.vsc_types_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (p = beg; p < end; p += strlen(p) + 1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (count >= VS_TYPES_MAX) {
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_types[count] = p;
911106dfb16696472af8c1b7b4c554a829354fa8jm ++count;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_exempt_file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * check if a file's size or type exempts it from virus scanning
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * If the file is exempt from virus scanning, allow will be set
911106dfb16696472af8c1b7b4c554a829354fa8jm * to define whether files access should be allowed (B_TRUE) or
911106dfb16696472af8c1b7b4c554a829354fa8jm * denied (B_FALSE)
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 1 exempt
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 scan required
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_exempt_file(vnode_t *vp, boolean_t *allow)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm struct vattr attr;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vp != NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vp->v_path != NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm attr.va_mask = AT_SIZE;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (VOP_GETATTR(vp, &attr, 0, kcred, NULL) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm *allow = B_FALSE;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (attr.va_size > vscan_svc_config.vsc_max_size) {
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__exempt__filesize, char *,
911106dfb16696472af8c1b7b4c554a829354fa8jm vp->v_path, int, *allow);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm *allow = (vscan_svc_config.vsc_allow) ? B_TRUE : B_FALSE;
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_exempt_filetype(vp->v_path)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE1(vscan__exempt__filetype, char *, vp->v_path);
911106dfb16696472af8c1b7b4c554a829354fa8jm *allow = B_TRUE;
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_exit(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_exempt_filetype
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Each entry in vscan_svc_types includes a rule indicator (+,-)
911106dfb16696472af8c1b7b4c554a829354fa8jm * followed by the match string for file types to which the rule
911106dfb16696472af8c1b7b4c554a829354fa8jm * applies. Look for first match of file type in vscan_svc_types
911106dfb16696472af8c1b7b4c554a829354fa8jm * and return 1 (exempt) if the indicator is '-', and 0 (not exempt)
911106dfb16696472af8c1b7b4c554a829354fa8jm * if the indicator is '+'.
911106dfb16696472af8c1b7b4c554a829354fa8jm * If vscan_svc_match_ext fails, or no match is found, return 0
911106dfb16696472af8c1b7b4c554a829354fa8jm * (not exempt)
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns 1: exempt, 0: not exempt
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_exempt_filetype(char *filepath)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int i, rc, exempt = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *filename, *ext;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_cfg_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((filename = strrchr(filepath, '/')) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm filename = filepath;
911106dfb16696472af8c1b7b4c554a829354fa8jm else
911106dfb16696472af8c1b7b4c554a829354fa8jm filename++;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ext = strrchr(filename, '.')) == NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm ext = "";
911106dfb16696472af8c1b7b4c554a829354fa8jm else
911106dfb16696472af8c1b7b4c554a829354fa8jm ext++;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < VS_TYPES_MAX; i ++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_types[i] == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = vscan_svc_match_ext(vscan_svc_types[i] + 1, ext, 1);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (rc == -1)
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm if (rc > 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__type__match, char *, ext,
911106dfb16696472af8c1b7b4c554a829354fa8jm char *, vscan_svc_types[i]);
911106dfb16696472af8c1b7b4c554a829354fa8jm exempt = (vscan_svc_types[i][0] == '-');
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (exempt);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_match_ext
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Performs a case-insensitive match for two strings. The first string
911106dfb16696472af8c1b7b4c554a829354fa8jm * argument can contain the wildcard characters '?' and '*'
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 no match
911106dfb16696472af8c1b7b4c554a829354fa8jm * 1 match
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 recursion error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_match_ext(char *patn, char *str, int depth)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int c1, c2;
911106dfb16696472af8c1b7b4c554a829354fa8jm if (depth > VS_EXT_RECURSE_DEPTH)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (;;) {
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (*patn) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case 0:
911106dfb16696472af8c1b7b4c554a829354fa8jm return (*str == 0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case '?':
911106dfb16696472af8c1b7b4c554a829354fa8jm if (*str != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm str++;
911106dfb16696472af8c1b7b4c554a829354fa8jm patn++;
911106dfb16696472af8c1b7b4c554a829354fa8jm continue;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case '*':
911106dfb16696472af8c1b7b4c554a829354fa8jm patn++;
911106dfb16696472af8c1b7b4c554a829354fa8jm if (*patn == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while (*str) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_match_ext(patn, str, depth + 1))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm str++;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm default:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (*str != *patn) {
911106dfb16696472af8c1b7b4c554a829354fa8jm c1 = *str;
911106dfb16696472af8c1b7b4c554a829354fa8jm c2 = *patn;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm c1 = tolower(c1);
911106dfb16696472af8c1b7b4c554a829354fa8jm c2 = tolower(c2);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (c1 != c2)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm str++;
911106dfb16696472af8c1b7b4c554a829354fa8jm patn++;
911106dfb16696472af8c1b7b4c554a829354fa8jm continue;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm /* NOT REACHED */
911106dfb16696472af8c1b7b4c554a829354fa8jm}