diff --git a/sbin/veriexec/veriexec.c b/sbin/veriexec/veriexec.c --- a/sbin/veriexec/veriexec.c +++ b/sbin/veriexec/veriexec.c @@ -53,7 +53,9 @@ veriexec_usage() { printf("%s", - "Usage:\tveriexec [-h] [-i state] [-C] [-xv state|verbosity] [path]\n"); + "Usage:\tveriexec [-h] [-i state] [-C path] [-S] [-v] [-z state] [path]\n" + "\t\tveriexec -x path...\n" + "\t\tveriexec -l path\n"); return (0); } @@ -148,7 +150,7 @@ dev_fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0); - while ((c = getopt(argc, argv, "hC:i:Sxvz:")) != -1) { + while ((c = getopt(argc, argv, "hC:i:Sxvz:l:")) != -1) { switch (c) { case 'h': /* Print usage info */ @@ -159,6 +161,21 @@ Cdir = optarg; break; + case 'l': + { + if (dev_fd < 0) { + err(EX_UNAVAILABLE, "cannot open veriexec"); + } + struct verified_exec_label lbl = { 0 }; + if (realpath(optarg, lbl.file) == NULL) { + err(EX_NOINPUT, "cannot resolve file"); + } + if (ioctl(dev_fd, VERIEXEC_GETLABEL, &lbl)) { + err(EX_UNAVAILABLE, "Cannot get veriexec label"); + } + printf("%s\n", lbl.label); + return (0); + } case 'i': /* Query the current state */ diff --git a/sys/dev/veriexec/veriexec_ioctl.h b/sys/dev/veriexec/veriexec_ioctl.h --- a/sys/dev/veriexec/veriexec_ioctl.h +++ b/sys/dev/veriexec/veriexec_ioctl.h @@ -51,6 +51,11 @@ char label[MAXLABELLEN]; }; +struct verified_exec_label { + char file[MAXPATHLEN]; + char label[MAXLABELLEN]; +}; + #define VERIEXEC_LOAD _IOW('S', 0x1, struct verified_exec_params) #define VERIEXEC_ACTIVE _IO('S', 0x2) /* start checking */ #define VERIEXEC_ENFORCE _IO('S', 0x3) /* fail exec */ @@ -61,6 +66,7 @@ #define VERIEXEC_SIGNED_LOAD _IOW('S', 0x8, struct verified_exec_params) #define VERIEXEC_GETVERSION _IOR('S', 0x9, int) /* get version */ #define VERIEXEC_LABEL_LOAD _IOW('S', 0xa, struct verified_exec_label_params) +#define VERIEXEC_GETLABEL _IOWR('S', 0xb, struct verified_exec_label) /* get label */ #define _PATH_DEV_VERIEXEC _PATH_DEV "veriexec" diff --git a/sys/dev/veriexec/verified_exec.c b/sys/dev/veriexec/verified_exec.c --- a/sys/dev/veriexec/verified_exec.c +++ b/sys/dev/veriexec/verified_exec.c @@ -89,6 +89,39 @@ return (error); } break; + case VERIEXEC_GETLABEL: + { + struct verified_exec_label *getlabel = (struct verified_exec_label*)data; + int flags = FREAD; + /* + * Get the attributes for the file name passed + * stash the file's device id and inode number + * along with it's fingerprint in a list for + * exec to use later. + */ + NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, + getlabel->file, td); + if ((error = vn_open(&nid, &flags, 0, NULL)) != 0) + return (error); + + error = VOP_GETATTR(nid.ni_vp, &vattr, td->td_ucred); + + VOP_UNLOCK(nid.ni_vp, 0); + (void) vn_close(nid.ni_vp, FREAD, td->td_ucred, td); + + if (error != 0) + return (error); + + mtx_lock(&ve_mutex); + if (!mac_veriexec_metadata_copy_label(vattr.va_fsid, vattr.va_fileid, + vattr.va_gen, getlabel->label, sizeof(getlabel->label))) + { + error = EAUTH; + } + mtx_unlock(&ve_mutex); + return (error); + } + break; default: break; } diff --git a/sys/security/mac_veriexec/mac_veriexec.h b/sys/security/mac_veriexec/mac_veriexec.h --- a/sys/security/mac_veriexec/mac_veriexec.h +++ b/sys/security/mac_veriexec/mac_veriexec.h @@ -157,6 +157,8 @@ int override); int mac_veriexec_metadata_has_file(dev_t fsid, long fileid, unsigned long gen); +int mac_veriexec_metadata_copy_label(dev_t fsid, long fileid, + unsigned long gen, char* label_buf, size_t buf_size); int mac_veriexec_proc_is_trusted(struct ucred *cred, struct proc *p); #endif diff --git a/sys/security/mac_veriexec/veriexec_metadata.c b/sys/security/mac_veriexec/veriexec_metadata.c --- a/sys/security/mac_veriexec/veriexec_metadata.c +++ b/sys/security/mac_veriexec/veriexec_metadata.c @@ -233,6 +233,38 @@ return (mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL, VERIEXEC_FILES_FIRST) != NULL); } +/** + * @brief Copies the label associated with a file. + * + * @param fsid file system identifier to look for + * @param fileid file to look for + * @param gen generation of file + * @param label_buf label output buffer + * @param buf_size buffer size + * + * @return 1 if there is an entry in the meta-data store, 0 otherwise. + */ +int +mac_veriexec_metadata_copy_label(dev_t fsid, long fileid, + unsigned long gen, char* label_buf, size_t buf_size) +{ + struct mac_veriexec_file_info *ip = NULL; + + if (!label_buf || buf_size == 0) + return (0); + + ip = mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL, + VERIEXEC_FILES_FIRST); + if (!ip) + return (0); + + if (!ip->label) + *label_buf = '\0'; + else + strlcpy(label_buf, ip->label, buf_size); + + return (1); +} /** * @brief Search the list of devices looking for the one given, in order to