1718c8510SRobert Watson /* 2718c8510SRobert Watson * Copyright (c) 1999-2005 Apple Computer, Inc. 3718c8510SRobert Watson * All rights reserved. 4718c8510SRobert Watson * 5718c8510SRobert Watson * Redistribution and use in source and binary forms, with or without 6718c8510SRobert Watson * modification, are permitted provided that the following conditions 7718c8510SRobert Watson * are met: 8718c8510SRobert Watson * 1. Redistributions of source code must retain the above copyright 9718c8510SRobert Watson * notice, this list of conditions and the following disclaimer. 10718c8510SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 11718c8510SRobert Watson * notice, this list of conditions and the following disclaimer in the 12718c8510SRobert Watson * documentation and/or other materials provided with the distribution. 13718c8510SRobert Watson * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14718c8510SRobert Watson * its contributors may be used to endorse or promote products derived 15718c8510SRobert Watson * from this software without specific prior written permission. 16718c8510SRobert Watson * 17718c8510SRobert Watson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18718c8510SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19718c8510SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20718c8510SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21718c8510SRobert Watson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22718c8510SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23718c8510SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24718c8510SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25718c8510SRobert Watson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26718c8510SRobert Watson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27718c8510SRobert Watson * POSSIBILITY OF SUCH DAMAGE. 28718c8510SRobert Watson * 29718c8510SRobert Watson * $FreeBSD$ 30718c8510SRobert Watson */ 31718c8510SRobert Watson 32718c8510SRobert Watson #include <sys/param.h> 33718c8510SRobert Watson #include <sys/filedesc.h> 34718c8510SRobert Watson #include <sys/ipc.h> 35718c8510SRobert Watson #include <sys/mount.h> 36718c8510SRobert Watson #include <sys/proc.h> 37718c8510SRobert Watson #include <sys/socket.h> 38718c8510SRobert Watson #include <sys/socketvar.h> 39718c8510SRobert Watson #include <sys/protosw.h> 40718c8510SRobert Watson #include <sys/domain.h> 41718c8510SRobert Watson #include <sys/systm.h> 42718c8510SRobert Watson #include <sys/un.h> 43718c8510SRobert Watson #include <sys/vnode.h> 44718c8510SRobert Watson 45718c8510SRobert Watson #include <netinet/in.h> 46718c8510SRobert Watson #include <netinet/in_pcb.h> 47718c8510SRobert Watson 48718c8510SRobert Watson #include <security/audit/audit.h> 49718c8510SRobert Watson #include <security/audit/audit_private.h> 50718c8510SRobert Watson 51718c8510SRobert Watson /* 52718c8510SRobert Watson * Calls to manipulate elements of the audit record structure from system 53718c8510SRobert Watson * call code. Macro wrappers will prevent this functions from being 54718c8510SRobert Watson * entered if auditing is disabled, avoiding the function call cost. We 55718c8510SRobert Watson * check the thread audit record pointer anyway, as the audit condition 56718c8510SRobert Watson * could change, and pre-selection may not have allocated an audit 57718c8510SRobert Watson * record for this event. 58718c8510SRobert Watson * 59718c8510SRobert Watson * XXXAUDIT: Should we assert, in each case, that this field of the record 60718c8510SRobert Watson * hasn't already been filled in? 61718c8510SRobert Watson */ 62718c8510SRobert Watson void 63718c8510SRobert Watson audit_arg_addr(void * addr) 64718c8510SRobert Watson { 65718c8510SRobert Watson struct kaudit_record *ar; 66718c8510SRobert Watson 67718c8510SRobert Watson ar = currecord(); 68718c8510SRobert Watson if (ar == NULL) 69718c8510SRobert Watson return; 70718c8510SRobert Watson 71718c8510SRobert Watson ar->k_ar.ar_arg_addr = addr; 72718c8510SRobert Watson ARG_SET_VALID(ar, ARG_ADDR); 73718c8510SRobert Watson } 74718c8510SRobert Watson 75718c8510SRobert Watson void 76718c8510SRobert Watson audit_arg_exit(int status, int retval) 77718c8510SRobert Watson { 78718c8510SRobert Watson struct kaudit_record *ar; 79718c8510SRobert Watson 80718c8510SRobert Watson ar = currecord(); 81718c8510SRobert Watson if (ar == NULL) 82718c8510SRobert Watson return; 83718c8510SRobert Watson 84718c8510SRobert Watson ar->k_ar.ar_arg_exitstatus = status; 85718c8510SRobert Watson ar->k_ar.ar_arg_exitretval = retval; 86718c8510SRobert Watson ARG_SET_VALID(ar, ARG_EXIT); 87718c8510SRobert Watson } 88718c8510SRobert Watson 89718c8510SRobert Watson void 90718c8510SRobert Watson audit_arg_len(int len) 91718c8510SRobert Watson { 92718c8510SRobert Watson struct kaudit_record *ar; 93718c8510SRobert Watson 94718c8510SRobert Watson ar = currecord(); 95718c8510SRobert Watson if (ar == NULL) 96718c8510SRobert Watson return; 97718c8510SRobert Watson 98718c8510SRobert Watson ar->k_ar.ar_arg_len = len; 99718c8510SRobert Watson ARG_SET_VALID(ar, ARG_LEN); 100718c8510SRobert Watson } 101718c8510SRobert Watson 102718c8510SRobert Watson void 103718c8510SRobert Watson audit_arg_fd(int fd) 104718c8510SRobert Watson { 105718c8510SRobert Watson struct kaudit_record *ar; 106718c8510SRobert Watson 107718c8510SRobert Watson ar = currecord(); 108718c8510SRobert Watson if (ar == NULL) 109718c8510SRobert Watson return; 110718c8510SRobert Watson 111718c8510SRobert Watson ar->k_ar.ar_arg_fd = fd; 112718c8510SRobert Watson ARG_SET_VALID(ar, ARG_FD); 113718c8510SRobert Watson } 114718c8510SRobert Watson 115718c8510SRobert Watson void 116718c8510SRobert Watson audit_arg_fflags(int fflags) 117718c8510SRobert Watson { 118718c8510SRobert Watson struct kaudit_record *ar; 119718c8510SRobert Watson 120718c8510SRobert Watson ar = currecord(); 121718c8510SRobert Watson if (ar == NULL) 122718c8510SRobert Watson return; 123718c8510SRobert Watson 124718c8510SRobert Watson ar->k_ar.ar_arg_fflags = fflags; 125718c8510SRobert Watson ARG_SET_VALID(ar, ARG_FFLAGS); 126718c8510SRobert Watson } 127718c8510SRobert Watson 128718c8510SRobert Watson void 129718c8510SRobert Watson audit_arg_gid(gid_t gid) 130718c8510SRobert Watson { 131718c8510SRobert Watson struct kaudit_record *ar; 132718c8510SRobert Watson 133718c8510SRobert Watson ar = currecord(); 134718c8510SRobert Watson if (ar == NULL) 135718c8510SRobert Watson return; 136718c8510SRobert Watson 137718c8510SRobert Watson ar->k_ar.ar_arg_gid = gid; 138718c8510SRobert Watson ARG_SET_VALID(ar, ARG_GID); 139718c8510SRobert Watson } 140718c8510SRobert Watson 141718c8510SRobert Watson void 142718c8510SRobert Watson audit_arg_uid(uid_t uid) 143718c8510SRobert Watson { 144718c8510SRobert Watson struct kaudit_record *ar; 145718c8510SRobert Watson 146718c8510SRobert Watson ar = currecord(); 147718c8510SRobert Watson if (ar == NULL) 148718c8510SRobert Watson return; 149718c8510SRobert Watson 150718c8510SRobert Watson ar->k_ar.ar_arg_uid = uid; 151718c8510SRobert Watson ARG_SET_VALID(ar, ARG_UID); 152718c8510SRobert Watson } 153718c8510SRobert Watson 154718c8510SRobert Watson void 155718c8510SRobert Watson audit_arg_egid(gid_t egid) 156718c8510SRobert Watson { 157718c8510SRobert Watson struct kaudit_record *ar; 158718c8510SRobert Watson 159718c8510SRobert Watson ar = currecord(); 160718c8510SRobert Watson if (ar == NULL) 161718c8510SRobert Watson return; 162718c8510SRobert Watson 163718c8510SRobert Watson ar->k_ar.ar_arg_egid = egid; 164718c8510SRobert Watson ARG_SET_VALID(ar, ARG_EGID); 165718c8510SRobert Watson } 166718c8510SRobert Watson 167718c8510SRobert Watson void 168718c8510SRobert Watson audit_arg_euid(uid_t euid) 169718c8510SRobert Watson { 170718c8510SRobert Watson struct kaudit_record *ar; 171718c8510SRobert Watson 172718c8510SRobert Watson ar = currecord(); 173718c8510SRobert Watson if (ar == NULL) 174718c8510SRobert Watson return; 175718c8510SRobert Watson 176718c8510SRobert Watson ar->k_ar.ar_arg_euid = euid; 177718c8510SRobert Watson ARG_SET_VALID(ar, ARG_EUID); 178718c8510SRobert Watson } 179718c8510SRobert Watson 180718c8510SRobert Watson void 181718c8510SRobert Watson audit_arg_rgid(gid_t rgid) 182718c8510SRobert Watson { 183718c8510SRobert Watson struct kaudit_record *ar; 184718c8510SRobert Watson 185718c8510SRobert Watson ar = currecord(); 186718c8510SRobert Watson if (ar == NULL) 187718c8510SRobert Watson return; 188718c8510SRobert Watson 189718c8510SRobert Watson ar->k_ar.ar_arg_rgid = rgid; 190718c8510SRobert Watson ARG_SET_VALID(ar, ARG_RGID); 191718c8510SRobert Watson } 192718c8510SRobert Watson 193718c8510SRobert Watson void 194718c8510SRobert Watson audit_arg_ruid(uid_t ruid) 195718c8510SRobert Watson { 196718c8510SRobert Watson struct kaudit_record *ar; 197718c8510SRobert Watson 198718c8510SRobert Watson ar = currecord(); 199718c8510SRobert Watson if (ar == NULL) 200718c8510SRobert Watson return; 201718c8510SRobert Watson 202718c8510SRobert Watson ar->k_ar.ar_arg_ruid = ruid; 203718c8510SRobert Watson ARG_SET_VALID(ar, ARG_RUID); 204718c8510SRobert Watson } 205718c8510SRobert Watson 206718c8510SRobert Watson void 207718c8510SRobert Watson audit_arg_sgid(gid_t sgid) 208718c8510SRobert Watson { 209718c8510SRobert Watson struct kaudit_record *ar; 210718c8510SRobert Watson 211718c8510SRobert Watson ar = currecord(); 212718c8510SRobert Watson if (ar == NULL) 213718c8510SRobert Watson return; 214718c8510SRobert Watson 215718c8510SRobert Watson ar->k_ar.ar_arg_sgid = sgid; 216718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SGID); 217718c8510SRobert Watson } 218718c8510SRobert Watson 219718c8510SRobert Watson void 220718c8510SRobert Watson audit_arg_suid(uid_t suid) 221718c8510SRobert Watson { 222718c8510SRobert Watson struct kaudit_record *ar; 223718c8510SRobert Watson 224718c8510SRobert Watson ar = currecord(); 225718c8510SRobert Watson if (ar == NULL) 226718c8510SRobert Watson return; 227718c8510SRobert Watson 228718c8510SRobert Watson ar->k_ar.ar_arg_suid = suid; 229718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SUID); 230718c8510SRobert Watson } 231718c8510SRobert Watson 232718c8510SRobert Watson void 233718c8510SRobert Watson audit_arg_groupset(gid_t *gidset, u_int gidset_size) 234718c8510SRobert Watson { 235718c8510SRobert Watson int i; 236718c8510SRobert Watson struct kaudit_record *ar; 237718c8510SRobert Watson 238718c8510SRobert Watson ar = currecord(); 239718c8510SRobert Watson if (ar == NULL) 240718c8510SRobert Watson return; 241718c8510SRobert Watson 242718c8510SRobert Watson for (i = 0; i < gidset_size; i++) 243718c8510SRobert Watson ar->k_ar.ar_arg_groups.gidset[i] = gidset[i]; 244718c8510SRobert Watson ar->k_ar.ar_arg_groups.gidset_size = gidset_size; 245718c8510SRobert Watson ARG_SET_VALID(ar, ARG_GROUPSET); 246718c8510SRobert Watson } 247718c8510SRobert Watson 248718c8510SRobert Watson void 249718c8510SRobert Watson audit_arg_login(char *login) 250718c8510SRobert Watson { 251718c8510SRobert Watson struct kaudit_record *ar; 252718c8510SRobert Watson 253718c8510SRobert Watson ar = currecord(); 254718c8510SRobert Watson if (ar == NULL) 255718c8510SRobert Watson return; 256718c8510SRobert Watson 257718c8510SRobert Watson strlcpy(ar->k_ar.ar_arg_login, login, MAXLOGNAME); 258718c8510SRobert Watson ARG_SET_VALID(ar, ARG_LOGIN); 259718c8510SRobert Watson } 260718c8510SRobert Watson 261718c8510SRobert Watson void 262718c8510SRobert Watson audit_arg_ctlname(int *name, int namelen) 263718c8510SRobert Watson { 264718c8510SRobert Watson struct kaudit_record *ar; 265718c8510SRobert Watson 266718c8510SRobert Watson ar = currecord(); 267718c8510SRobert Watson if (ar == NULL) 268718c8510SRobert Watson return; 269718c8510SRobert Watson 270718c8510SRobert Watson bcopy(name, &ar->k_ar.ar_arg_ctlname, namelen * sizeof(int)); 271718c8510SRobert Watson ar->k_ar.ar_arg_len = namelen; 272718c8510SRobert Watson ARG_SET_VALID(ar, ARG_CTLNAME | ARG_LEN); 273718c8510SRobert Watson } 274718c8510SRobert Watson 275718c8510SRobert Watson void 276718c8510SRobert Watson audit_arg_mask(int mask) 277718c8510SRobert Watson { 278718c8510SRobert Watson struct kaudit_record *ar; 279718c8510SRobert Watson 280718c8510SRobert Watson ar = currecord(); 281718c8510SRobert Watson if (ar == NULL) 282718c8510SRobert Watson return; 283718c8510SRobert Watson 284718c8510SRobert Watson ar->k_ar.ar_arg_mask = mask; 285718c8510SRobert Watson ARG_SET_VALID(ar, ARG_MASK); 286718c8510SRobert Watson } 287718c8510SRobert Watson 288718c8510SRobert Watson void 289718c8510SRobert Watson audit_arg_mode(mode_t mode) 290718c8510SRobert Watson { 291718c8510SRobert Watson struct kaudit_record *ar; 292718c8510SRobert Watson 293718c8510SRobert Watson ar = currecord(); 294718c8510SRobert Watson if (ar == NULL) 295718c8510SRobert Watson return; 296718c8510SRobert Watson 297718c8510SRobert Watson ar->k_ar.ar_arg_mode = mode; 298718c8510SRobert Watson ARG_SET_VALID(ar, ARG_MODE); 299718c8510SRobert Watson } 300718c8510SRobert Watson 301718c8510SRobert Watson void 302718c8510SRobert Watson audit_arg_dev(int dev) 303718c8510SRobert Watson { 304718c8510SRobert Watson struct kaudit_record *ar; 305718c8510SRobert Watson 306718c8510SRobert Watson ar = currecord(); 307718c8510SRobert Watson if (ar == NULL) 308718c8510SRobert Watson return; 309718c8510SRobert Watson 310718c8510SRobert Watson ar->k_ar.ar_arg_dev = dev; 311718c8510SRobert Watson ARG_SET_VALID(ar, ARG_DEV); 312718c8510SRobert Watson } 313718c8510SRobert Watson 314718c8510SRobert Watson void 315718c8510SRobert Watson audit_arg_value(long value) 316718c8510SRobert Watson { 317718c8510SRobert Watson struct kaudit_record *ar; 318718c8510SRobert Watson 319718c8510SRobert Watson ar = currecord(); 320718c8510SRobert Watson if (ar == NULL) 321718c8510SRobert Watson return; 322718c8510SRobert Watson 323718c8510SRobert Watson ar->k_ar.ar_arg_value = value; 324718c8510SRobert Watson ARG_SET_VALID(ar, ARG_VALUE); 325718c8510SRobert Watson } 326718c8510SRobert Watson 327718c8510SRobert Watson void 328718c8510SRobert Watson audit_arg_owner(uid_t uid, gid_t gid) 329718c8510SRobert Watson { 330718c8510SRobert Watson struct kaudit_record *ar; 331718c8510SRobert Watson 332718c8510SRobert Watson ar = currecord(); 333718c8510SRobert Watson if (ar == NULL) 334718c8510SRobert Watson return; 335718c8510SRobert Watson 336718c8510SRobert Watson ar->k_ar.ar_arg_uid = uid; 337718c8510SRobert Watson ar->k_ar.ar_arg_gid = gid; 338718c8510SRobert Watson ARG_SET_VALID(ar, ARG_UID | ARG_GID); 339718c8510SRobert Watson } 340718c8510SRobert Watson 341718c8510SRobert Watson void 342718c8510SRobert Watson audit_arg_pid(pid_t pid) 343718c8510SRobert Watson { 344718c8510SRobert Watson struct kaudit_record *ar; 345718c8510SRobert Watson 346718c8510SRobert Watson ar = currecord(); 347718c8510SRobert Watson if (ar == NULL) 348718c8510SRobert Watson return; 349718c8510SRobert Watson 350718c8510SRobert Watson ar->k_ar.ar_arg_pid = pid; 351718c8510SRobert Watson ARG_SET_VALID(ar, ARG_PID); 352718c8510SRobert Watson } 353718c8510SRobert Watson 354718c8510SRobert Watson void 355718c8510SRobert Watson audit_arg_process(struct proc *p) 356718c8510SRobert Watson { 357718c8510SRobert Watson struct kaudit_record *ar; 358718c8510SRobert Watson 359718c8510SRobert Watson ar = currecord(); 360718c8510SRobert Watson if ((ar == NULL) || (p == NULL)) 361718c8510SRobert Watson return; 362718c8510SRobert Watson 363718c8510SRobert Watson /* 364718c8510SRobert Watson * XXXAUDIT: PROC_LOCK_ASSERT(p); 365718c8510SRobert Watson */ 366718c8510SRobert Watson ar->k_ar.ar_arg_auid = p->p_au->ai_auid; 367718c8510SRobert Watson ar->k_ar.ar_arg_euid = p->p_ucred->cr_uid; 368718c8510SRobert Watson ar->k_ar.ar_arg_egid = p->p_ucred->cr_groups[0]; 369718c8510SRobert Watson ar->k_ar.ar_arg_ruid = p->p_ucred->cr_ruid; 370718c8510SRobert Watson ar->k_ar.ar_arg_rgid = p->p_ucred->cr_rgid; 371718c8510SRobert Watson ar->k_ar.ar_arg_asid = p->p_au->ai_asid; 372718c8510SRobert Watson ar->k_ar.ar_arg_termid = p->p_au->ai_termid; 373718c8510SRobert Watson ARG_SET_VALID(ar, ARG_AUID | ARG_EUID | ARG_EGID | ARG_RUID | 374718c8510SRobert Watson ARG_RGID | ARG_ASID | ARG_TERMID | ARG_PROCESS); 375718c8510SRobert Watson } 376718c8510SRobert Watson 377718c8510SRobert Watson void 378718c8510SRobert Watson audit_arg_signum(u_int signum) 379718c8510SRobert Watson { 380718c8510SRobert Watson struct kaudit_record *ar; 381718c8510SRobert Watson 382718c8510SRobert Watson ar = currecord(); 383718c8510SRobert Watson if (ar == NULL) 384718c8510SRobert Watson return; 385718c8510SRobert Watson 386718c8510SRobert Watson ar->k_ar.ar_arg_signum = signum; 387718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SIGNUM); 388718c8510SRobert Watson } 389718c8510SRobert Watson 390718c8510SRobert Watson void 391718c8510SRobert Watson audit_arg_socket(int sodomain, int sotype, int soprotocol) 392718c8510SRobert Watson { 393718c8510SRobert Watson struct kaudit_record *ar; 394718c8510SRobert Watson 395718c8510SRobert Watson ar = currecord(); 396718c8510SRobert Watson if (ar == NULL) 397718c8510SRobert Watson return; 398718c8510SRobert Watson 399718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_domain = sodomain; 400718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_type = sotype; 401718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_protocol = soprotocol; 402718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SOCKINFO); 403718c8510SRobert Watson } 404718c8510SRobert Watson 405718c8510SRobert Watson /* 406718c8510SRobert Watson * XXXAUDIT: Argument here should be 'sa' not 'so'. Caller is responsible 407718c8510SRobert Watson * for synchronizing access to the source of the address. 408718c8510SRobert Watson */ 409718c8510SRobert Watson void 410718c8510SRobert Watson audit_arg_sockaddr(struct thread *td, struct sockaddr *so) 411718c8510SRobert Watson { 412718c8510SRobert Watson struct kaudit_record *ar; 413718c8510SRobert Watson 414718c8510SRobert Watson ar = currecord(); 415718c8510SRobert Watson if (ar == NULL || td == NULL || so == NULL) 416718c8510SRobert Watson return; 417718c8510SRobert Watson 418718c8510SRobert Watson bcopy(so, &ar->k_ar.ar_arg_sockaddr, sizeof(ar->k_ar.ar_arg_sockaddr)); 419718c8510SRobert Watson switch (so->sa_family) { 420718c8510SRobert Watson case AF_INET: 421718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SADDRINET); 422718c8510SRobert Watson break; 423718c8510SRobert Watson 424718c8510SRobert Watson case AF_INET6: 425718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SADDRINET6); 426718c8510SRobert Watson break; 427718c8510SRobert Watson 428718c8510SRobert Watson case AF_UNIX: 429718c8510SRobert Watson audit_arg_upath(td, ((struct sockaddr_un *)so)->sun_path, 430718c8510SRobert Watson ARG_UPATH1); 431718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SADDRUNIX); 432718c8510SRobert Watson break; 433718c8510SRobert Watson /* XXXAUDIT: default:? */ 434718c8510SRobert Watson } 435718c8510SRobert Watson } 436718c8510SRobert Watson 437718c8510SRobert Watson void 438718c8510SRobert Watson audit_arg_auid(uid_t auid) 439718c8510SRobert Watson { 440718c8510SRobert Watson struct kaudit_record *ar; 441718c8510SRobert Watson 442718c8510SRobert Watson ar = currecord(); 443718c8510SRobert Watson if (ar == NULL) 444718c8510SRobert Watson return; 445718c8510SRobert Watson 446718c8510SRobert Watson ar->k_ar.ar_arg_auid = auid; 447718c8510SRobert Watson ARG_SET_VALID(ar, ARG_AUID); 448718c8510SRobert Watson } 449718c8510SRobert Watson 450718c8510SRobert Watson void 451718c8510SRobert Watson audit_arg_auditinfo(struct auditinfo *au_info) 452718c8510SRobert Watson { 453718c8510SRobert Watson struct kaudit_record *ar; 454718c8510SRobert Watson 455718c8510SRobert Watson ar = currecord(); 456718c8510SRobert Watson if (ar == NULL) 457718c8510SRobert Watson return; 458718c8510SRobert Watson 459718c8510SRobert Watson ar->k_ar.ar_arg_auid = au_info->ai_auid; 460718c8510SRobert Watson ar->k_ar.ar_arg_asid = au_info->ai_asid; 461718c8510SRobert Watson ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success; 462718c8510SRobert Watson ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure; 463718c8510SRobert Watson ar->k_ar.ar_arg_termid.port = au_info->ai_termid.port; 464718c8510SRobert Watson ar->k_ar.ar_arg_termid.machine = au_info->ai_termid.machine; 465718c8510SRobert Watson ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID); 466718c8510SRobert Watson } 467718c8510SRobert Watson 468718c8510SRobert Watson void 469718c8510SRobert Watson audit_arg_text(char *text) 470718c8510SRobert Watson { 471718c8510SRobert Watson struct kaudit_record *ar; 472718c8510SRobert Watson 473718c8510SRobert Watson ar = currecord(); 474718c8510SRobert Watson if (ar == NULL) 475718c8510SRobert Watson return; 476718c8510SRobert Watson 477718c8510SRobert Watson /* 478718c8510SRobert Watson * XXXAUDIT: Why do we accept a possibly NULL string here? 479718c8510SRobert Watson */ 480718c8510SRobert Watson /* Invalidate the text string */ 481718c8510SRobert Watson ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT); 482718c8510SRobert Watson if (text == NULL) 483718c8510SRobert Watson return; 484718c8510SRobert Watson 485718c8510SRobert Watson if (ar->k_ar.ar_arg_text == NULL) 486718c8510SRobert Watson ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT, 487718c8510SRobert Watson M_WAITOK); 488718c8510SRobert Watson 489718c8510SRobert Watson strncpy(ar->k_ar.ar_arg_text, text, MAXPATHLEN); 490718c8510SRobert Watson ARG_SET_VALID(ar, ARG_TEXT); 491718c8510SRobert Watson } 492718c8510SRobert Watson 493718c8510SRobert Watson void 494718c8510SRobert Watson audit_arg_cmd(int cmd) 495718c8510SRobert Watson { 496718c8510SRobert Watson struct kaudit_record *ar; 497718c8510SRobert Watson 498718c8510SRobert Watson ar = currecord(); 499718c8510SRobert Watson if (ar == NULL) 500718c8510SRobert Watson return; 501718c8510SRobert Watson 502718c8510SRobert Watson ar->k_ar.ar_arg_cmd = cmd; 503718c8510SRobert Watson ARG_SET_VALID(ar, ARG_CMD); 504718c8510SRobert Watson } 505718c8510SRobert Watson 506718c8510SRobert Watson void 507718c8510SRobert Watson audit_arg_svipc_cmd(int cmd) 508718c8510SRobert Watson { 509718c8510SRobert Watson struct kaudit_record *ar; 510718c8510SRobert Watson 511718c8510SRobert Watson ar = currecord(); 512718c8510SRobert Watson if (ar == NULL) 513718c8510SRobert Watson return; 514718c8510SRobert Watson 515718c8510SRobert Watson ar->k_ar.ar_arg_svipc_cmd = cmd; 516718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SVIPC_CMD); 517718c8510SRobert Watson } 518718c8510SRobert Watson 519718c8510SRobert Watson void 520718c8510SRobert Watson audit_arg_svipc_perm(struct ipc_perm *perm) 521718c8510SRobert Watson { 522718c8510SRobert Watson struct kaudit_record *ar; 523718c8510SRobert Watson 524718c8510SRobert Watson ar = currecord(); 525718c8510SRobert Watson if (ar == NULL) 526718c8510SRobert Watson return; 527718c8510SRobert Watson 528718c8510SRobert Watson bcopy(perm, &ar->k_ar.ar_arg_svipc_perm, 529718c8510SRobert Watson sizeof(ar->k_ar.ar_arg_svipc_perm)); 530718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SVIPC_PERM); 531718c8510SRobert Watson } 532718c8510SRobert Watson 533718c8510SRobert Watson void 534718c8510SRobert Watson audit_arg_svipc_id(int id) 535718c8510SRobert Watson { 536718c8510SRobert Watson struct kaudit_record *ar; 537718c8510SRobert Watson 538718c8510SRobert Watson ar = currecord(); 539718c8510SRobert Watson if (ar == NULL) 540718c8510SRobert Watson return; 541718c8510SRobert Watson 542718c8510SRobert Watson ar->k_ar.ar_arg_svipc_id = id; 543718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SVIPC_ID); 544718c8510SRobert Watson } 545718c8510SRobert Watson 546718c8510SRobert Watson void 547718c8510SRobert Watson audit_arg_svipc_addr(void * addr) 548718c8510SRobert Watson { 549718c8510SRobert Watson struct kaudit_record *ar; 550718c8510SRobert Watson 551718c8510SRobert Watson ar = currecord(); 552718c8510SRobert Watson if (ar == NULL) 553718c8510SRobert Watson return; 554718c8510SRobert Watson 555718c8510SRobert Watson ar->k_ar.ar_arg_svipc_addr = addr; 556718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SVIPC_ADDR); 557718c8510SRobert Watson } 558718c8510SRobert Watson 559718c8510SRobert Watson void 560718c8510SRobert Watson audit_arg_posix_ipc_perm(uid_t uid, gid_t gid, mode_t mode) 561718c8510SRobert Watson { 562718c8510SRobert Watson struct kaudit_record *ar; 563718c8510SRobert Watson 564718c8510SRobert Watson ar = currecord(); 565718c8510SRobert Watson if (ar == NULL) 566718c8510SRobert Watson return; 567718c8510SRobert Watson 568718c8510SRobert Watson ar->k_ar.ar_arg_pipc_perm.pipc_uid = uid; 569718c8510SRobert Watson ar->k_ar.ar_arg_pipc_perm.pipc_gid = gid; 570718c8510SRobert Watson ar->k_ar.ar_arg_pipc_perm.pipc_mode = mode; 571718c8510SRobert Watson ARG_SET_VALID(ar, ARG_POSIX_IPC_PERM); 572718c8510SRobert Watson } 573718c8510SRobert Watson 574718c8510SRobert Watson void 575718c8510SRobert Watson audit_arg_auditon(union auditon_udata *udata) 576718c8510SRobert Watson { 577718c8510SRobert Watson struct kaudit_record *ar; 578718c8510SRobert Watson 579718c8510SRobert Watson ar = currecord(); 580718c8510SRobert Watson if (ar == NULL) 581718c8510SRobert Watson return; 582718c8510SRobert Watson 583718c8510SRobert Watson bcopy((void *)udata, &ar->k_ar.ar_arg_auditon, 584718c8510SRobert Watson sizeof(ar->k_ar.ar_arg_auditon)); 585718c8510SRobert Watson ARG_SET_VALID(ar, ARG_AUDITON); 586718c8510SRobert Watson } 587718c8510SRobert Watson 588718c8510SRobert Watson /* 589718c8510SRobert Watson * Audit information about a file, either the file's vnode info, or its 590718c8510SRobert Watson * socket address info. 591718c8510SRobert Watson */ 592718c8510SRobert Watson void 593718c8510SRobert Watson audit_arg_file(struct proc *p, struct file *fp) 594718c8510SRobert Watson { 595718c8510SRobert Watson struct kaudit_record *ar; 596718c8510SRobert Watson struct socket *so; 597718c8510SRobert Watson struct inpcb *pcb; 598718c8510SRobert Watson struct vnode *vp; 599718c8510SRobert Watson int vfslocked; 600718c8510SRobert Watson 601718c8510SRobert Watson /* 602718c8510SRobert Watson * XXXAUDIT: Why is the (ar == NULL) test only in the socket case? 603718c8510SRobert Watson */ 604718c8510SRobert Watson switch (fp->f_type) { 605718c8510SRobert Watson case DTYPE_VNODE: 606718c8510SRobert Watson case DTYPE_FIFO: 607718c8510SRobert Watson /* 608718c8510SRobert Watson * XXXAUDIT: Only possibly to record as first vnode? 609718c8510SRobert Watson */ 610718c8510SRobert Watson vp = fp->f_vnode; 611718c8510SRobert Watson vfslocked = VFS_LOCK_GIANT(vp->v_mount); 612718c8510SRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); 613718c8510SRobert Watson audit_arg_vnode(vp, ARG_VNODE1); 614718c8510SRobert Watson VOP_UNLOCK(vp, 0, curthread); 615718c8510SRobert Watson VFS_UNLOCK_GIANT(vfslocked); 616718c8510SRobert Watson break; 617718c8510SRobert Watson 618718c8510SRobert Watson case DTYPE_SOCKET: 619718c8510SRobert Watson ar = currecord(); 620718c8510SRobert Watson if (ar == NULL) 621718c8510SRobert Watson return; 622718c8510SRobert Watson 623718c8510SRobert Watson /* 624718c8510SRobert Watson * XXXAUDIT: Socket locking? Inpcb locking? 625718c8510SRobert Watson */ 626718c8510SRobert Watson so = (struct socket *)fp->f_data; 627718c8510SRobert Watson if (INP_CHECK_SOCKAF(so, PF_INET)) { 628718c8510SRobert Watson if (so->so_pcb == NULL) 629718c8510SRobert Watson return; 630718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_type = 631718c8510SRobert Watson so->so_type; 632718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_domain = 633718c8510SRobert Watson INP_SOCKAF(so); 634718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_protocol = 635718c8510SRobert Watson so->so_proto->pr_protocol; 636718c8510SRobert Watson pcb = (struct inpcb *)so->so_pcb; 637718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_raddr = 638718c8510SRobert Watson pcb->inp_faddr.s_addr; 639718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_laddr = 640718c8510SRobert Watson pcb->inp_laddr.s_addr; 641718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_rport = 642718c8510SRobert Watson pcb->inp_fport; 643718c8510SRobert Watson ar->k_ar.ar_arg_sockinfo.so_lport = 644718c8510SRobert Watson pcb->inp_lport; 645718c8510SRobert Watson ARG_SET_VALID(ar, ARG_SOCKINFO); 646718c8510SRobert Watson } 647718c8510SRobert Watson break; 648718c8510SRobert Watson 649718c8510SRobert Watson default: 650718c8510SRobert Watson /* XXXAUDIT: else? */ 651718c8510SRobert Watson break; 652718c8510SRobert Watson } 653718c8510SRobert Watson 654718c8510SRobert Watson } 655718c8510SRobert Watson 656718c8510SRobert Watson /* 657718c8510SRobert Watson * Store a path as given by the user process for auditing into the audit 658718c8510SRobert Watson * record stored on the user thread. This function will allocate the memory to 659718c8510SRobert Watson * store the path info if not already available. This memory will be 660718c8510SRobert Watson * freed when the audit record is freed. 661718c8510SRobert Watson * 662718c8510SRobert Watson * XXXAUDIT: Possibly assert that the memory isn't already allocated? 663718c8510SRobert Watson */ 664718c8510SRobert Watson void 665718c8510SRobert Watson audit_arg_upath(struct thread *td, char *upath, u_int64_t flag) 666718c8510SRobert Watson { 667718c8510SRobert Watson struct kaudit_record *ar; 668718c8510SRobert Watson char **pathp; 669718c8510SRobert Watson 670718c8510SRobert Watson if (td == NULL || upath == NULL) 671718c8510SRobert Watson return; /* nothing to do! */ 672718c8510SRobert Watson 673718c8510SRobert Watson /* 674718c8510SRobert Watson * XXXAUDIT: Witness warning for possible sleep here? 675718c8510SRobert Watson */ 676718c8510SRobert Watson KASSERT((flag == ARG_UPATH1) || (flag == ARG_UPATH2), 677718c8510SRobert Watson ("audit_arg_upath: flag %llu", flag)); 678718c8510SRobert Watson KASSERT((flag != ARG_UPATH1) || (flag != ARG_UPATH2), 679718c8510SRobert Watson ("audit_arg_upath: flag %llu", flag)); 680718c8510SRobert Watson 681718c8510SRobert Watson ar = currecord(); 682718c8510SRobert Watson if (ar == NULL) 683718c8510SRobert Watson return; 684718c8510SRobert Watson 685718c8510SRobert Watson if (flag == ARG_UPATH1) 686718c8510SRobert Watson pathp = &ar->k_ar.ar_arg_upath1; 687718c8510SRobert Watson else 688718c8510SRobert Watson pathp = &ar->k_ar.ar_arg_upath2; 689718c8510SRobert Watson 690718c8510SRobert Watson if (*pathp == NULL) 691718c8510SRobert Watson *pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK); 692718c8510SRobert Watson 693718c8510SRobert Watson canon_path(td, upath, *pathp); 694718c8510SRobert Watson 695718c8510SRobert Watson ARG_SET_VALID(ar, flag); 696718c8510SRobert Watson } 697718c8510SRobert Watson 698718c8510SRobert Watson /* 699718c8510SRobert Watson * Function to save the path and vnode attr information into the audit 700718c8510SRobert Watson * record. 701718c8510SRobert Watson * 702718c8510SRobert Watson * It is assumed that the caller will hold any vnode locks necessary to 703718c8510SRobert Watson * perform a VOP_GETATTR() on the passed vnode. 704718c8510SRobert Watson * 705718c8510SRobert Watson * XXX: The attr code is very similar to vfs_vnops.c:vn_stat(), but 706718c8510SRobert Watson * always provides access to the generation number as we need that 707718c8510SRobert Watson * to construct the BSM file ID. 708718c8510SRobert Watson * XXX: We should accept the process argument from the caller, since 709718c8510SRobert Watson * it's very likely they already have a reference. 710718c8510SRobert Watson * XXX: Error handling in this function is poor. 711718c8510SRobert Watson * 712718c8510SRobert Watson * XXXAUDIT: Possibly KASSERT the path pointer is NULL? 713718c8510SRobert Watson */ 714718c8510SRobert Watson void 715718c8510SRobert Watson audit_arg_vnode(struct vnode *vp, u_int64_t flags) 716718c8510SRobert Watson { 717718c8510SRobert Watson struct kaudit_record *ar; 718718c8510SRobert Watson struct vattr vattr; 719718c8510SRobert Watson int error; 720718c8510SRobert Watson struct vnode_au_info *vnp; 721718c8510SRobert Watson struct thread *td; 722718c8510SRobert Watson 723718c8510SRobert Watson /* 724718c8510SRobert Watson * XXXAUDIT: Why is vp possibly NULL here? 725718c8510SRobert Watson */ 726718c8510SRobert Watson if (vp == NULL) 727718c8510SRobert Watson return; 728718c8510SRobert Watson 729718c8510SRobert Watson /* 730718c8510SRobert Watson * Assume that if the caller is calling audit_arg_vnode() on a 731718c8510SRobert Watson * non-MPSAFE vnode, then it will have acquired Giant. 732718c8510SRobert Watson */ 733718c8510SRobert Watson VFS_ASSERT_GIANT(vp->v_mount); 734718c8510SRobert Watson ASSERT_VOP_LOCKED(vp, "audit_arg_vnode"); 735718c8510SRobert Watson 736718c8510SRobert Watson ar = currecord(); 737718c8510SRobert Watson if (ar == NULL) /* This will be the case for unaudited system calls */ 738718c8510SRobert Watson return; 739718c8510SRobert Watson 740718c8510SRobert Watson /* 741718c8510SRobert Watson * XXXAUDIT: KASSERT argument validity instead? 742718c8510SRobert Watson * 743718c8510SRobert Watson * XXXAUDIT: The below clears, and then resets the flags for valid 744718c8510SRobert Watson * arguments. Ideally, either the new vnode is used, or the old one 745718c8510SRobert Watson * would be. 746718c8510SRobert Watson */ 747718c8510SRobert Watson if ((flags & (ARG_VNODE1 | ARG_VNODE2)) == 0) 748718c8510SRobert Watson return; 749718c8510SRobert Watson 750718c8510SRobert Watson td = curthread; 751718c8510SRobert Watson 752718c8510SRobert Watson if (flags & ARG_VNODE1) { 753718c8510SRobert Watson ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_VNODE1); 754718c8510SRobert Watson vnp = &ar->k_ar.ar_arg_vnode1; 755718c8510SRobert Watson } else { 756718c8510SRobert Watson ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_VNODE2); 757718c8510SRobert Watson vnp = &ar->k_ar.ar_arg_vnode2; 758718c8510SRobert Watson } 759718c8510SRobert Watson 760718c8510SRobert Watson error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); 761718c8510SRobert Watson if (error) { 762718c8510SRobert Watson /* XXX: How to handle this case? */ 763718c8510SRobert Watson return; 764718c8510SRobert Watson } 765718c8510SRobert Watson 766718c8510SRobert Watson vnp->vn_mode = vattr.va_mode; 767718c8510SRobert Watson vnp->vn_uid = vattr.va_uid; 768718c8510SRobert Watson vnp->vn_gid = vattr.va_gid; 769718c8510SRobert Watson vnp->vn_dev = vattr.va_rdev; 770718c8510SRobert Watson vnp->vn_fsid = vattr.va_fsid; 771718c8510SRobert Watson vnp->vn_fileid = vattr.va_fileid; 772718c8510SRobert Watson vnp->vn_gen = vattr.va_gen; 773718c8510SRobert Watson if (flags & ARG_VNODE1) 774718c8510SRobert Watson ARG_SET_VALID(ar, ARG_VNODE1); 775718c8510SRobert Watson else 776718c8510SRobert Watson ARG_SET_VALID(ar, ARG_VNODE2); 777718c8510SRobert Watson } 778718c8510SRobert Watson 779718c8510SRobert Watson /* 780718c8510SRobert Watson * The close() system call uses it's own audit call to capture the 781718c8510SRobert Watson * path/vnode information because those pieces are not easily obtained 782718c8510SRobert Watson * within the system call itself. 783718c8510SRobert Watson */ 784718c8510SRobert Watson void 785718c8510SRobert Watson audit_sysclose(struct thread *td, int fd) 786718c8510SRobert Watson { 787718c8510SRobert Watson struct vnode *vp; 788718c8510SRobert Watson struct file *fp; 789718c8510SRobert Watson int vfslocked; 790718c8510SRobert Watson 791718c8510SRobert Watson audit_arg_fd(fd); 792718c8510SRobert Watson 793718c8510SRobert Watson if (getvnode(td->td_proc->p_fd, fd, &fp) != 0) 794718c8510SRobert Watson return; 795718c8510SRobert Watson 796718c8510SRobert Watson vp = fp->f_vnode; 797718c8510SRobert Watson vfslocked = VFS_LOCK_GIANT(vp->v_mount); 798718c8510SRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 799718c8510SRobert Watson audit_arg_vnode(vp, ARG_VNODE1); 800718c8510SRobert Watson VOP_UNLOCK(vp, 0, td); 801718c8510SRobert Watson VFS_UNLOCK_GIANT(vfslocked); 802718c8510SRobert Watson fdrop(fp, td); 803718c8510SRobert Watson } 804