vscan_svc.c revision 911106dfb16696472af8c1b7b4c554a829354fa8
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/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * Copyright 2007 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;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint8_t vsf_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint8_t vsf_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint64_t vsf_size;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_scanstamp_t vsf_scanstamp;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint32_t vsf_access;
911106dfb16696472af8c1b7b4c554a829354fa8jm} vscan_file_t;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic vscan_file_t vscan_svc_files[VS_DRV_MAX_FILES + 1];
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_files_idx = 0; /* idx of most recently allocated slot */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic kcondvar_t vscan_svc_cv; /* wait for slot in vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic kcondvar_t vscan_svc_file_cv[VS_DRV_MAX_FILES + 1]; /* wait for scan */
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);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vscan_svc_notify_scan_complete(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_getattr(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_setattr(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 int i;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_init(&vscan_svc_mutex, NULL, MUTEX_DRIVER, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_init(&vscan_svc_cfg_mutex, NULL, MUTEX_DRIVER, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* create task queue for async requests */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((vscan_svc_taskq = taskq_create("vscan", VS_TASKQ_NUM_THREADS,
911106dfb16696472af8c1b7b4c554a829354fa8jm MINCLSYSPRI, 1, INT_MAX, 0)) == NULL) {
911106dfb16696472af8c1b7b4c554a829354fa8jm cmn_err(CE_WARN, "All scan requests will be "
911106dfb16696472af8c1b7b4c554a829354fa8jm "processed synchronously");
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* initialize vscan_svc_files table */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(&vscan_svc_files, 0, sizeof (vscan_svc_files));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* initialize condition variables */
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_init(&vscan_svc_cv, NULL, CV_DEFAULT, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i <= VS_DRV_MAX_FILES; i++)
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_init(&vscan_svc_file_cv[i], NULL, CV_DEFAULT, NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_fini
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_fini()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int i;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vscan_svc_enabled == B_FALSE);
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(vscan_svc_in_use() == B_FALSE);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_taskq)
911106dfb16696472af8c1b7b4c554a829354fa8jm taskq_destroy(vscan_svc_taskq);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_destroy(&vscan_svc_cv);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i <= VS_DRV_MAX_FILES; i++)
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_destroy(&vscan_svc_file_cv[i]);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_destroy(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_destroy(&vscan_svc_cfg_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_enable
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_enable(boolean_t enable)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_enabled = enable;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (enable)
911106dfb16696472af8c1b7b4c554a829354fa8jm fs_vscan_register(vscan_svc_scan_file);
911106dfb16696472af8c1b7b4c554a829354fa8jm else
911106dfb16696472af8c1b7b4c554a829354fa8jm fs_vscan_register(NULL);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_in_use
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmboolean_t
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_in_use()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm boolean_t rc;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = (vscan_svc_req_count > 0) ? B_TRUE : B_FALSE;
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 *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Currently scanstamps cannot be created on files that existed
911106dfb16696472af8c1b7b4c554a829354fa8jm * prior to scanstamp being a system attribute. Thus an attempt
911106dfb16696472af8c1b7b4c554a829354fa8jm * to access the scanstamp may fail. For this reason if vscan_getattr
911106dfb16696472af8c1b7b4c554a829354fa8jm * or vscan_setattr fails, it is retried excluding scanstamp.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_do_scan(vscan_fs_req_t *req)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int rc = 0, idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_scan_req_t *scan_req;
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 */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((idx = vscan_svc_wait_for_scan(req->vsr_vp)) == -1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* insert the scan request into vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jm idx = vscan_svc_insert_file(req);
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);
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = vscan_door_scan_file(scan_req);
911106dfb16696472af8c1b7b4c554a829354fa8jm mutex_enter(&vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (rc == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_parse_rsp(idx, scan_req);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) vscan_svc_setattr(idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm kmem_free(scan_req, sizeof (vs_scan_req_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm cmn_err(CE_WARN, "Can't access xattr for %s\n",
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_req.
911106dfb16696472af8c1b7b4c554a829354fa8jm vsr_vp->v_path);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if vscan not enabled (shutting down), allow ACCESS */
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_access = VS_ACCESS_ALLOW;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* When a scan completes the result is saved in vscan_svc_files */
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = (vscan_svc_files[idx].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
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;
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 */
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_wait_count++;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__wait__scan, vscan_file_t *,
911106dfb16696472af8c1b7b4c554a829354fa8jm &(vscan_svc_files[idx]), int, idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while (vscan_svc_files[idx].vsf_access == VS_ACCESS_UNDEFINED)
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_wait(&(vscan_svc_file_cv[idx]), &vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].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 * vscan_svc_files_idx is the most recently allocated slot,
911106dfb16696472af8c1b7b4c554a829354fa8jm * start search at next slot.
911106dfb16696472af8c1b7b4c554a829354fa8jm * slot 0 is reserved for control interface
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns idx of slot, or -1 if not found
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_find_slot(void)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int idx, start;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((start = vscan_svc_files_idx + 1) > VS_DRV_MAX_FILES)
911106dfb16696472af8c1b7b4c554a829354fa8jm start = 1;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (idx = start; idx <= VS_DRV_MAX_FILES; idx++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_files[idx].vsf_req.vsr_vp == NULL) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files_idx = idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (idx = 1; idx < start; idx++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_files[idx].vsf_req.vsr_vp == NULL) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files_idx = idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
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;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while ((idx = vscan_svc_find_slot()) == -1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE1(vscan__wait__slot, vscan_file_t *,
911106dfb16696472af8c1b7b4c554a829354fa8jm &(vscan_svc_files[idx]));
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_wait_count++;
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_wait(&(vscan_svc_cv), &vscan_svc_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_wait_count--;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(&vscan_svc_files[idx], 0, sizeof (vscan_file_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_req = *req;
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_modified = 1;
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_access = VS_ACCESS_UNDEFINED;
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{
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_file_t *slot;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_files[idx].vsf_wait_count != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm slot = &vscan_svc_files[idx];
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__release, char *, slot->vsf_req.vsr_vp->v_path,
911106dfb16696472af8c1b7b4c554a829354fa8jm int, idx);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(slot, 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;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm req = &vscan_svc_files[idx].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);
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_size = vscan_svc_files[idx].vsf_size;
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_modified = vscan_svc_files[idx].vsf_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_quarantined = vscan_svc_files[idx].vsf_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_flags = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strncpy(scan_req->vsr_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].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{
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_access = scan_req->vsr_access;
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_modified = scan_req->vsr_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_quarantined = scan_req->vsr_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strncpy(vscan_svc_files[idx].vsf_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm scan_req->vsr_scanstamp, sizeof (vs_scanstamp_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_notify_scan_complete
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * signal vscan_svc_file_cv and vscan_svc_cv to wake threads waiting
911106dfb16696472af8c1b7b4c554a829354fa8jm * for the scan result for the specified file (vscan_svc_file_cv)
911106dfb16696472af8c1b7b4c554a829354fa8jm * or for a slot in vscan_svc_files table (vscan_svc_cv)
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_notify_scan_complete(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if someone waiting for result, cv_signal */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_files[idx].vsf_wait_count > 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm cv_signal(&vscan_svc_file_cv[idx]);
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 *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Get the vscan related system attributes and AT_SIZE.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_getattr(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm xvattr_t xvattr;
911106dfb16696472af8c1b7b4c554a829354fa8jm xoptattr_t *xoap = NULL;
911106dfb16696472af8c1b7b4c554a829354fa8jm vnode_t *vp;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((vp = vscan_svc_files[idx].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;
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
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_size = xvattr.xva_vattr.va_size;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (XVA_ISSET_RTN(&xvattr, XAT_AV_MODIFIED) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_modified = xoap->xoa_av_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (XVA_ISSET_RTN(&xvattr, XAT_AV_QUARANTINED) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_quarantined = xoap->xoa_av_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (XVA_ISSET_RTN(&xvattr, XAT_AV_SCANSTAMP) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memcpy(vscan_svc_files[idx].vsf_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE1(vscan__attr, vscan_file_t *, &(vscan_svc_files[idx]));
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_setattr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Set the vscan related system attributes.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Caller must already have vscan_svc_mutex
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvscan_svc_setattr(int idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm xvattr_t xvattr;
911106dfb16696472af8c1b7b4c554a829354fa8jm xoptattr_t *xoap = NULL;
911106dfb16696472af8c1b7b4c554a829354fa8jm vnode_t *vp;
911106dfb16696472af8c1b7b4c554a829354fa8jm int len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ASSERT(MUTEX_HELD(&vscan_svc_mutex));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((vp = vscan_svc_files[idx].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
911106dfb16696472af8c1b7b4c554a829354fa8jm XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED);
911106dfb16696472af8c1b7b4c554a829354fa8jm xoap->xoa_av_modified = vscan_svc_files[idx].vsf_modified;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED);
911106dfb16696472af8c1b7b4c554a829354fa8jm xoap->xoa_av_quarantined = vscan_svc_files[idx].vsf_quarantined;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm XVA_SET_REQ(&xvattr, XAT_AV_SCANSTAMP);
911106dfb16696472af8c1b7b4c554a829354fa8jm len = strlen(vscan_svc_files[idx].vsf_scanstamp);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memcpy(xoap->xoa_av_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm vscan_svc_files[idx].vsf_scanstamp, len);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if access is denied, set mtime to invalidate client cache */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vscan_svc_files[idx].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
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE1(vscan__attr, vscan_file_t *, &(vscan_svc_files[idx]));
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}