vscan_svc.c revision d3d50737e566cade9a08d73d2af95105ac7cd960
911106dfb16696472af8c1b7b4c554a829354fa8jm * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911106dfb16696472af8c1b7b4c554a829354fa8jm * See the License for the specific language governing permissions
911106dfb16696472af8c1b7b4c554a829354fa8jm * and limitations under the License.
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 * CDDL HEADER END
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Use is subject to license terms.
bfc848c632c9eacb2a640246d96e198f1b185c03jm#define VS_REQS_DEFAULT 20000 /* pending scan requests - reql */
bfc848c632c9eacb2a640246d96e198f1b185c03jm#define VS_SCANWAIT_DEFAULT 15*60 /* seconds to wait for scan result */
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* access derived from scan result (VS_STATUS_XXX) and file attributes */
911106dfb16696472af8c1b7b4c554a829354fa8jm#define tolower(C) (((C) >= 'A' && (C) <= 'Z') ? (C) - 'A' + 'a' : (C))
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* global variables - tunable via /etc/system */
bfc848c632c9eacb2a640246d96e198f1b185c03jmuint32_t vs_reqs_max = VS_REQS_DEFAULT; /* max scan requests */
bfc848c632c9eacb2a640246d96e198f1b185c03jmuint32_t vs_nodes_max = VS_NODES_DEFAULT; /* max in-progress scan requests */
bfc848c632c9eacb2a640246d96e198f1b185c03jmuint32_t vs_workers = VS_WORKERS_DEFAULT; /* max workers send reqs to vscand */
bfc848c632c9eacb2a640246d96e198f1b185c03jmuint32_t vs_scan_wait = VS_SCANWAIT_DEFAULT; /* secs to wait for scan result */
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_state
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_UNCONFIG |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | svc_init | svc_fini
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_IDLE |<----|
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | svc_enable |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * |<----------------| |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+ | |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_ENABLED |--| |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | svc_disable | handler thread exit,
bfc848c632c9eacb2a640246d96e198f1b185c03jm * v | all requests complete
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_DISABLED |-----|
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +-----------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jm * svc_enable may occur when we are already in the ENABLED
bfc848c632c9eacb2a640246d96e198f1b185c03jm * state if vscand has exited without clean shutdown and
bfc848c632c9eacb2a640246d96e198f1b185c03jm * then reconnected within the delayed disable time period
bfc848c632c9eacb2a640246d96e198f1b185c03jm * (vs_reconnect_timeout) - see vscan_drv
bfc848c632c9eacb2a640246d96e198f1b185c03jmtypedef enum {
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic vscan_svc_state_t vscan_svc_state = VS_SVC_UNCONFIG;
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_req_state
bfc848c632c9eacb2a640246d96e198f1b185c03jm * When a scan request is received from the file system it is
bfc848c632c9eacb2a640246d96e198f1b185c03jm * identified in or inserted into the vscan_svc_reql (INIT).
bfc848c632c9eacb2a640246d96e198f1b185c03jm * If the request is asynchronous 0 is then returned to the caller.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * If the request is synchronous the req's refcnt is incremented
bfc848c632c9eacb2a640246d96e198f1b185c03jm * and the caller waits for the request to complete.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * The refcnt is also incremented when the request is inserted
bfc848c632c9eacb2a640246d96e198f1b185c03jm * in vscan_svc_nodes, and decremented on scan_complete.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_handler processes requests from the request list,
bfc848c632c9eacb2a640246d96e198f1b185c03jm * inserting them into vscan_svc_nodes and the task queue (QUEUED).
bfc848c632c9eacb2a640246d96e198f1b185c03jm * When the task queue call back (vscan_svc_do_scan) is invoked
bfc848c632c9eacb2a640246d96e198f1b185c03jm * the request transitions to IN_PROGRESS state. If the request
bfc848c632c9eacb2a640246d96e198f1b185c03jm * is sucessfully sent to vscand (door_call) and the door response
bfc848c632c9eacb2a640246d96e198f1b185c03jm * is SCANNING then the scan result will be received asynchronously.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Although unusual, it is possible that the async response is
bfc848c632c9eacb2a640246d96e198f1b185c03jm * received before the door call returns (hence the ASYNC_COMPLETE
bfc848c632c9eacb2a640246d96e198f1b185c03jm * When the result has been determined / received,
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_scan_complete is invoked to transition the request to
bfc848c632c9eacb2a640246d96e198f1b185c03jm * COMPLETE state, decrement refcnt and signal all waiting callers.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * When the last waiting caller has processed the result (refcnt == 0)
bfc848c632c9eacb2a640246d96e198f1b185c03jm * the request is removed from vscan_svc_reql and vscan_svc_nodes
bfc848c632c9eacb2a640246d96e198f1b185c03jm * and deleted.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | reql_insert | refcnt == 0
bfc848c632c9eacb2a640246d96e198f1b185c03jm * v | (delete)
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +------------------------+ +---------------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_REQ_INIT | -----DISABLE----> | VS_SVC_REQ_COMPLETE |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +------------------------+ +---------------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | insert_req, tq_dispatch |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +------------------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_REQ_QUEUED | scan_complete
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +------------------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | tq_callback (do_scan) |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * v scan not req'd, error, |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +------------------------+ or door_result != SCANNING |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_REQ_IN_PROGRESS |----------------->-------------|
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +------------------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | | door_result == SCANNING |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | +---------------------------+ async result |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | | VS_SVC_REQ_SCANNING |-------->---------|
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | +---------------------------+ |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | async result |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +---------------------------+ door_result = SCANNING |
bfc848c632c9eacb2a640246d96e198f1b185c03jm * | VS_SVC_REQ_ASYNC_COMPLETE |-------->------------------|
bfc848c632c9eacb2a640246d96e198f1b185c03jm * +---------------------------+
bfc848c632c9eacb2a640246d96e198f1b185c03jmtypedef enum {
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_reql - the list of pending and in-progress scan requests
bfc848c632c9eacb2a640246d96e198f1b185c03jmtypedef struct vscan_req {
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_nodes - table of files being scanned
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 * Instance 0 is reserved for the daemon/driver control
911106dfb16696472af8c1b7b4c554a829354fa8jm * interface: enable/configure/disable
bfc848c632c9eacb2a640246d96e198f1b185c03jmtypedef struct vscan_svc_node {
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* vscan_svc_taskq - queue of requests waiting to be sent to vscand */
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* counts of entries in vscan_svc_reql, vscan_svc_nodes & vscan_svc_taskq */
bfc848c632c9eacb2a640246d96e198f1b185c03jmtypedef struct {
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_mutex protects the data pertaining to scan requests:
bfc848c632c9eacb2a640246d96e198f1b185c03jm * request list - vscan_svc_reql
bfc848c632c9eacb2a640246d96e198f1b185c03jm * node table - vscan_svc_nodes
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* unique request id for vscand request/response correlation */
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_cfg_mutex protects the configuration data:
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_config, vscan_svc_types
911106dfb16696472af8c1b7b4c554a829354fa8jm/* configuration data - for virus scan exemption */
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* thread to insert reql entries into vscan_svc_nodes & vscan_svc_taskq */
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic vscan_req_t *vscan_svc_reql_next; /* next pending scan request */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* local functions */
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void vscan_svc_taskq_callback(void *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_exempt_filetype(char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_match_ext(char *, char *, int);
53c110294d8b1410cabc201a52f94b03ae2ef448jmstatic void vscan_svc_process_scan_result(int);
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void vscan_svc_remove_req(int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vscan_svc_getattr(int);
53c110294d8b1410cabc201a52f94b03ae2ef448jmstatic int vscan_svc_setattr(int, int);
bfc848c632c9eacb2a640246d96e198f1b185c03jm/* thread to insert reql entries into vscan_svc_nodes & vscan_svc_taskq */
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void vscan_svc_reql_handler(void);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_init
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (-1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm mutex_init(&vscan_svc_cfg_mutex, NULL, MUTEX_DEFAULT, NULL);
bfc848c632c9eacb2a640246d96e198f1b185c03jm vscan_svc_nodes_sz = sizeof (vscan_svc_node_t) * (vs_nodes_max + 1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm vscan_svc_nodes = kmem_zalloc(vscan_svc_nodes_sz, KM_SLEEP);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_fini
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_enable
bfc848c632c9eacb2a640246d96e198f1b185c03jm * it's possible (and okay) for vscan_svc_enable to be
bfc848c632c9eacb2a640246d96e198f1b185c03jm * called when already enabled if vscand reconnects
bfc848c632c9eacb2a640246d96e198f1b185c03jm * during a delayed disable
bfc848c632c9eacb2a640246d96e198f1b185c03jm vscan_svc_taskq = taskq_create("vscan_taskq", vs_workers,
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* ready to start processing requests */
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (-1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (0);
53c110294d8b1410cabc201a52f94b03ae2ef448jm * vscan_svc_disable
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Resources allocated during vscan_svc_enable are free'd by
bfc848c632c9eacb2a640246d96e198f1b185c03jm * the handler thread immediately prior to exiting
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_in_use
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_get_vnode
911106dfb16696472af8c1b7b4c554a829354fa8jm * Get the file vnode indexed by idx.
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (vp);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_scan_file
911106dfb16696472af8c1b7b4c554a829354fa8jm * This function is the entry point for the file system to
911106dfb16696472af8c1b7b4c554a829354fa8jm * request that a file be virus scanned.
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE2(vscan__scan__file, char *, vp->v_path, int, async);
911106dfb16696472af8c1b7b4c554a829354fa8jm /* check if size or type exempts file from scanning */
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (0);
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* insert (or find) request in list */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* asynchronous request: return 0 */
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (0);
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* synchronous scan request: wait for result */
bfc848c632c9eacb2a640246d96e198f1b185c03jm while ((time_left > 0) && (req->vsr_state != VS_SVC_REQ_COMPLETE)) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni time_left = cv_reltimedwait_sig(&(req->vsr_cv),
bfc848c632c9eacb2a640246d96e198f1b185c03jm cmn_err(CE_WARN, "Virus scan request timeout %s (%d) \n",
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_reql_handler
bfc848c632c9eacb2a640246d96e198f1b185c03jm * inserts scan requests (from vscan_svc_reql) into
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_nodes and vscan_svc_taskq
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm for (;;) {
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* free resources allocated durining enable */
bfc848c632c9eacb2a640246d96e198f1b185c03jm * If disabled, scan_complete any pending requests.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Otherwise insert pending requests into vscan_svc_nodes
bfc848c632c9eacb2a640246d96e198f1b185c03jm * and vscan_svc_taskq. If no slots are available in
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_nodes break loop and wait for one
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* insert request into vscan_svc_nodes */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* add the scan request into the taskq */
bfc848c632c9eacb2a640246d96e198f1b185c03jm DTRACE_PROBE2(vscan__req__counts, char *, "handler wait",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&vscan_svc_reql_cv, &vscan_svc_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni SEC_TO_TICK(VS_REQL_HANDLER_TIMEOUT), TR_CLOCK_TICK);
bfc848c632c9eacb2a640246d96e198f1b185c03jm DTRACE_PROBE2(vscan__req__counts, char *, "handler wake",
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_do_scan
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Note: To avoid potential deadlock it is important that
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_mutex is not held during the call to
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_drv_create_note. vscan_drv_create_note enters
bfc848c632c9eacb2a640246d96e198f1b185c03jm * the vscan_drv_mutex and it is possible that a thread
bfc848c632c9eacb2a640246d96e198f1b185c03jm * holding that mutex could be waiting for vscan_svc_mutex.
53c110294d8b1410cabc201a52f94b03ae2ef448jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* if vscan not enabled (shutting down), allow ACCESS */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* valid scan_req ptr guaranteed */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* free up mutex around create node and door call */
bfc848c632c9eacb2a640246d96e198f1b185c03jm } else { /* async response */
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_populate_req
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Allocate a scan request to be sent to vscand, populating it
bfc848c632c9eacb2a640246d96e198f1b185c03jm * from the data in vscan_svc_nodes[idx].
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Returns: scan request object
bfc848c632c9eacb2a640246d96e198f1b185c03jm scan_req = kmem_zalloc(sizeof (vs_scan_req_t), KM_SLEEP);
bfc848c632c9eacb2a640246d96e198f1b185c03jm (void) strncpy(scan_req->vsr_path, req->vsr_vp->v_path, MAXPATHLEN);
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_scan_complete
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_delete_req
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_scan_result
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Invoked from vscan_drv.c on receipt of an ioctl containing
bfc848c632c9eacb2a640246d96e198f1b185c03jm * an async scan result (VS_DRV_IOCTL_RESULT)
bfc848c632c9eacb2a640246d96e198f1b185c03jm * If the vsr_seqnum in the response does not match that in the
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_nodes entry the result is discarded.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_scan_abort
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Abort in-progress scan requests.
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_process_scan_result
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Sets vsn_access and updates file attributes based on vsn_result,
bfc848c632c9eacb2a640246d96e198f1b185c03jm * as follows:
bfc848c632c9eacb2a640246d96e198f1b185c03jm * VS_STATUS_INFECTED
bfc848c632c9eacb2a640246d96e198f1b185c03jm * deny access, set quarantine attribute, clear scanstamp
bfc848c632c9eacb2a640246d96e198f1b185c03jm * VS_STATUS_CLEAN
bfc848c632c9eacb2a640246d96e198f1b185c03jm * allow access, set scanstamp,
bfc848c632c9eacb2a640246d96e198f1b185c03jm * if file not modified since scan initiated, clear modified attribute
bfc848c632c9eacb2a640246d96e198f1b185c03jm * VS_STATUS_NO_SCAN
bfc848c632c9eacb2a640246d96e198f1b185c03jm * deny access if file quarantined, otherwise allow access
bfc848c632c9eacb2a640246d96e198f1b185c03jm * VS_STATUS_UNDEFINED, VS_STATUS_ERROR
bfc848c632c9eacb2a640246d96e198f1b185c03jm * deny access if file quarantined, modified or no scanstamp
bfc848c632c9eacb2a640246d96e198f1b185c03jm * otherwise, allow access
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* if mtime has changed, don't clear the modified attribute */
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_getattr
53c110294d8b1410cabc201a52f94b03ae2ef448jm * Get the vscan related system attributes, AT_SIZE & AT_MTIME.
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm /* get the attributes */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (VOP_GETATTR(vp, (vattr_t *)&xvattr, 0, kcred, NULL) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm "file system does not support virus scanning");
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm node->vsn_mtime.tv_sec = xvattr.xva_vattr.va_mtime.tv_sec;
bfc848c632c9eacb2a640246d96e198f1b185c03jm node->vsn_mtime.tv_nsec = xvattr.xva_vattr.va_mtime.tv_nsec;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_setattr
911106dfb16696472af8c1b7b4c554a829354fa8jm * Set the vscan related system attributes.
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm /* update the attributes */
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if access is denied, set mtime to invalidate client cache */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (VOP_SETATTR(vp, (vattr_t *)&xvattr, 0, kcred, NULL) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_configure
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 (void) memset(vscan_svc_types, 0, sizeof (vscan_svc_types));
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_exempt_file
911106dfb16696472af8c1b7b4c554a829354fa8jm * check if a file's size or type exempts it from virus scanning
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 * Returns: 1 exempt
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 scan required
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm *allow = (vscan_svc_config.vsc_allow) ? B_TRUE : B_FALSE;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm DTRACE_PROBE1(vscan__exempt__filetype, char *, vp->v_path);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_exempt_filetype
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 * Returns 1: exempt, 0: not exempt
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < VS_TYPES_MAX; i ++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = vscan_svc_match_ext(vscan_svc_types[i] + 1, ext, 1);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (rc > 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm * vscan_svc_match_ext
911106dfb16696472af8c1b7b4c554a829354fa8jm * Performs a case-insensitive match for two strings. The first string
911106dfb16696472af8c1b7b4c554a829354fa8jm * argument can contain the wildcard characters '?' and '*'
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 no match
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 recursion error
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm for (;;) {
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (*patn) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (*str == 0);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (*str != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (*patn == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm while (*str) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm /* NOT REACHED */
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_insert_req
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Insert request in next available available slot in vscan_svc_nodes
bfc848c632c9eacb2a640246d96e198f1b185c03jm * Returns: idx of slot, or -1 if no slot available
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (-1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm return (-1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_remove_req
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void
bfc848c632c9eacb2a640246d96e198f1b185c03jm if (idx != 0) {
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_reql_find
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_reql_insert
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* if request already in list then return it */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* if list is full return NULL */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* create a new request and insert into list */
bfc848c632c9eacb2a640246d96e198f1b185c03jm req->vsr_refcnt = 1; /* decremented in vscan_svc_scan_complete */
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* wake reql handler thread */
bfc848c632c9eacb2a640246d96e198f1b185c03jm * vscan_svc_reql_remove
bfc848c632c9eacb2a640246d96e198f1b185c03jmstatic void