Blame src/OVAL/probes/fsdev.c

Packit Service 569379
/**
Packit Service 569379
 * @file   fsdev.c
Packit Service 569379
 * @brief  fsdev API implementation
Packit Service 569379
 * @author "Daniel Kopecek" <dkopecek@redhat.com>
Packit Service 569379
 *
Packit Service 569379
 */
Packit Service 569379
/*
Packit Service 569379
 * Copyright 2009 Red Hat Inc., Durham, North Carolina.
Packit Service 569379
 * All Rights Reserved.
Packit Service 569379
 *
Packit Service 569379
 * This library is free software; you can redistribute it and/or
Packit Service 569379
 * modify it under the terms of the GNU Lesser General Public
Packit Service 569379
 * License as published by the Free Software Foundation; either
Packit Service 569379
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 569379
 *
Packit Service 569379
 * This library is distributed in the hope that it will be useful,
Packit Service 569379
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 569379
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 569379
 * Lesser General Public License for more details.
Packit Service 569379
 *
Packit Service 569379
 * You should have received a copy of the GNU Lesser General Public
Packit Service 569379
 * License along with this library; if not, write to the Free Software
Packit Service 569379
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Packit Service 569379
 *
Packit Service 569379
 * Authors:
Packit Service 569379
 *      "Daniel Kopecek" <dkopecek@redhat.com>
Packit Service 569379
 */
Packit Service 569379
Packit Service 569379
#ifdef HAVE_CONFIG_H
Packit Service 569379
#include <config.h>
Packit Service 569379
#endif
Packit Service 569379
Packit Service 569379
#include <stdio.h>
Packit Service 569379
#include <stddef.h>
Packit Service 569379
#include <string.h>
Packit Service 569379
#include <ctype.h>
Packit Service 569379
#include <stdlib.h>
Packit Service 569379
#include <sys/types.h>
Packit Service 569379
#include <sys/stat.h>
Packit Service 569379
#include <errno.h>
Packit Service 569379
Packit Service 569379
#if defined(OS_LINUX)
Packit Service 569379
# include <mntent.h>
Packit Service 569379
# include <unistd.h>
Packit Service 569379
#elif defined(OS_SOLARIS)
Packit Service 569379
# include <sys/mnttab.h>
Packit Service 569379
# include <sys/mntent.h>
Packit Service 569379
# include <sys/unistd.h>
Packit Service 569379
#elif defined(OS_FREEBSD) || defined(OS_APPLE)
Packit Service 569379
# include <sys/param.h>
Packit Service 569379
# include <sys/ucred.h>
Packit Service 569379
# include <sys/mount.h>
Packit Service 569379
#elif defined(OS_AIX)
Packit Service 569379
# include <unistd.h>
Packit Service 569379
# include <mntent.h>
Packit Service 569379
# include <fshelp.h>
Packit Service 569379
# include <sys/vfs.h>
Packit Service 569379
# include <sys/vmount.h>
Packit Service 569379
# define _PATH_MOUNTED MOUNTED
Packit Service 569379
#else
Packit Service 569379
# error "Sorry, your OS isn't supported."
Packit Service 569379
#endif
Packit Service 569379
Packit Service 569379
#include "fsdev.h"
Packit Service 5b50fa
#include "common/util.h"
Packit Service 569379
Packit Service 569379
/**
Packit Service 569379
 * Compare two dev_t variables.
Packit Service 569379
 */
Packit Service 569379
static int fsdev_cmp(const void *a, const void *b)
Packit Service 569379
{
Packit Service 569379
	return memcmp(a, b, sizeof(dev_t));
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
#if defined(OS_LINUX) || defined(OS_AIX)
Packit Service 569379
Packit Service 569379
#define DEVID_ARRAY_SIZE 16
Packit Service 569379
#define DEVID_ARRAY_ADD  8
Packit Service 569379
Packit Service 569379
#if defined(OS_LINUX)
Packit Service 569379
static int is_local_fs(struct mntent *ment)
Packit Service 569379
{
Packit Service 569379
	/*
Packit Service 569379
	 * When type of the filesystem is autofs, it means the mtab entry
Packit Service 569379
	 * describes the autofs configuration, which means ment->mnt_fsname
Packit Service 569379
	 * is a path to the relevant autofs map, eg. /etc/auto.misc. In this
Packit Service 569379
	 * situation, the following code which analyses ment->mnt_type would
Packit Service 569379
	 * not work. When the filesystem handled by autofs is mounted, there
Packit Service 569379
	 * is another different entry in mtab which contains the real block
Packit Service 569379
	 * special device or remote filesystem in ment->mnt_fsname, and that
Packit Service 569379
	 * will be parsed in a different call of this function.
Packit Service 569379
	 */
Packit Service 569379
	if (!strcmp(ment->mnt_type, "autofs")) {
Packit Service 569379
		return 0;
Packit Service 569379
	}
Packit Service 569379
Packit Service 5b50fa
	/*
Packit Service 5b50fa
	 * The following code is inspired by systemd, function fstype_is_network:
Packit Service 5b50fa
	 * https://github.com/systemd/systemd/blob/21fd6bc263f49b57867d90d2e1f9f255e5509134/src/basic/mountpoint-util.c#L290
Packit Service 569379
	 */
Packit Service 569379
Packit Service 5b50fa
	const char *fstype = ment->mnt_type;
Packit Service 5b50fa
	if (oscap_str_startswith(fstype, "fuse.")) {
Packit Service 5b50fa
		fstype += strlen("fuse.");
Packit Service 5b50fa
	}
Packit Service 5b50fa
	const char *network_fs[] = {
Packit Service 5b50fa
		"afs",
Packit Service 5b50fa
		"ceph",
Packit Service 5b50fa
		"cifs",
Packit Service 5b50fa
		"smb3",
Packit Service 5b50fa
		"smbfs",
Packit Service 5b50fa
		"sshfs",
Packit Service 5b50fa
		"ncpfs",
Packit Service 5b50fa
		"ncp",
Packit Service 5b50fa
		"nfs",
Packit Service 5b50fa
		"nfs4",
Packit Service 5b50fa
		"gfs",
Packit Service 5b50fa
		"gfs2",
Packit Service 5b50fa
		"glusterfs",
Packit Service 5b50fa
		"gpfs",
Packit Service 5b50fa
		"pvfs2", /* OrangeFS */
Packit Service 5b50fa
		"ocfs2",
Packit Service 5b50fa
		"lustre",
Packit Service 5b50fa
		"davfs",
Packit Service 5b50fa
		NULL
Packit Service 5b50fa
	};
Packit Service 5b50fa
	for (int i = 0; network_fs[i]; i++) {
Packit Service 5b50fa
		if (!strcmp(network_fs[i], fstype)) {
Packit Service 5b50fa
			return 0;
Packit Service 5b50fa
		}
Packit Service 5b50fa
	}
Packit Service 569379
	return 1;
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
#elif defined(OS_AIX)
Packit Service 569379
static int is_local_fs(struct mntent *ment)
Packit Service 569379
{
Packit Service 569379
	int i;
Packit Service 569379
	struct vfs_ent *e;
Packit Service 569379
Packit Service 569379
	static const int remote_fs_types[] = {
Packit Service 569379
		MNT_NFS,
Packit Service 569379
		MNT_NFS3,
Packit Service 569379
		MNT_AUTOFS, /* remote? */
Packit Service 569379
		MNT_NFS4,
Packit Service 569379
		MNT_RFS4,
Packit Service 569379
		MNT_CIFS,
Packit Service 569379
		MNT_BADVFS  /* end mark */
Packit Service 569379
	};
Packit Service 569379
Packit Service 569379
	for (i = 0; remote_fs_types[i] != MNT_BADVFS; i++) {
Packit Service 569379
		e = getvfsbytype(remote_fs_types[i]);
Packit Service 569379
		if (e != NULL
Packit Service 569379
		    && e->vfsent_name != NULL
Packit Service 569379
		    && strcmp(ment->mnt_type, e->vfsent_name) == 0) {
Packit Service 569379
			return 0;
Packit Service 569379
		}
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	return 1;
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
#endif /* OS_AIX */
Packit Service 569379
Packit Service 569379
static fsdev_t *__fsdev_init(fsdev_t *lfs)
Packit Service 569379
{
Packit Service 569379
	int e;
Packit Service 569379
	FILE *fp;
Packit Service 569379
	size_t i;
Packit Service 569379
Packit Service 569379
	struct mntent *ment;
Packit Service 569379
	struct stat st;
Packit Service 569379
Packit Service 569379
	fp = setmntent(_PATH_MOUNTED, "r");
Packit Service 569379
	if (fp == NULL) {
Packit Service 569379
		e = errno;
Packit Service 569379
		free(lfs);
Packit Service 569379
		errno = e;
Packit Service 569379
		return (NULL);
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	lfs->ids = malloc(sizeof(dev_t) * DEVID_ARRAY_SIZE);
Packit Service 569379
Packit Service 569379
	if (lfs->ids == NULL) {
Packit Service 569379
		e = errno;
Packit Service 569379
		free(lfs);
Packit Service 569379
		endmntent(fp);
Packit Service 569379
		errno = e;
Packit Service 569379
		return (NULL);
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	lfs->cnt = DEVID_ARRAY_SIZE;
Packit Service 569379
	i = 0;
Packit Service 569379
Packit Service 569379
	while ((ment = getmntent(fp)) != NULL) {
Packit Service 569379
		if (!is_local_fs(ment))
Packit Service 569379
			continue;
Packit Service 569379
		if (stat(ment->mnt_dir, &st) != 0)
Packit Service 569379
			continue;
Packit Service 569379
		if (i >= lfs->cnt) {
Packit Service 569379
			lfs->cnt += DEVID_ARRAY_ADD;
Packit Service 569379
			lfs->ids = realloc(lfs->ids, sizeof(dev_t) * lfs->cnt);
Packit Service 569379
		}
Packit Service 569379
		memcpy(&(lfs->ids[i++]), &st.st_dev, sizeof(dev_t));
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	endmntent(fp);
Packit Service 569379
Packit Service 569379
	lfs->ids = realloc(lfs->ids, sizeof(dev_t) * i);
Packit Service 569379
	lfs->cnt = (lfs->ids == NULL ? 0 : i);
Packit Service 569379
Packit Service 569379
	return (lfs);
Packit Service 569379
}
Packit Service 569379
#elif defined(OS_FREEBSD) || defined(OS_APPLE)
Packit Service 569379
static fsdev_t *__fsdev_init(fsdev_t *lfs)
Packit Service 569379
{
Packit Service 569379
	struct statfs *mntbuf = NULL;
Packit Service 569379
	struct stat st;
Packit Service 569379
	int i;
Packit Service 569379
Packit Service 569379
	lfs->cnt = getmntinfo(&mntbuf, (fs == NULL ? MNT_LOCAL : 0) | MNT_NOWAIT);
Packit Service 569379
	lfs->ids = malloc(sizeof(dev_t) * lfs->cnt);
Packit Service 569379
Packit Service 569379
	for (i = 0; i < lfs->cnt; ++i) {
Packit Service 569379
		if (stat(mntbuf[i].f_mntonname, &st) != 0)
Packit Service 569379
			continue;
Packit Service 569379
Packit Service 569379
		memcpy(&(lfs->ids[i]), &st.st_dev, sizeof(dev_t));
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	if (i != lfs->cnt) {
Packit Service 569379
		lfs->ids = realloc(lfs->ids, sizeof(dev_t) * i);
Packit Service 569379
		lfs->cnt = i;
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	return (lfs);
Packit Service 569379
}
Packit Service 569379
#elif defined(OS_SOLARIS)
Packit Service 569379
Packit Service 569379
#define DEVID_ARRAY_SIZE 16
Packit Service 569379
#define DEVID_ARRAY_ADD  8
Packit Service 569379
Packit Service 569379
static fsdev_t *__fsdev_init(fsdev_t *lfs)
Packit Service 569379
{
Packit Service 569379
	int e;
Packit Service 569379
	FILE *fp;
Packit Service 569379
	size_t i;
Packit Service 569379
Packit Service 569379
	struct mnttab mentbuf;
Packit Service 569379
	struct stat st;
Packit Service 569379
Packit Service 569379
	fp = fopen(MNTTAB, "r");
Packit Service 569379
	if (fp == NULL) {
Packit Service 569379
		e = errno;
Packit Service 569379
		free(lfs);
Packit Service 569379
		errno = e;
Packit Service 569379
		return (NULL);
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	lfs->ids = malloc(sizeof(dev_t) * DEVID_ARRAY_SIZE);
Packit Service 569379
Packit Service 569379
	if (lfs->ids == NULL) {
Packit Service 569379
		e = errno;
Packit Service 569379
		free(lfs);
Packit Service 569379
                fclose(fp);
Packit Service 569379
		errno = e;
Packit Service 569379
		return (NULL);
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	lfs->cnt = DEVID_ARRAY_SIZE;
Packit Service 569379
	i = 0;
Packit Service 569379
Packit Service 569379
	while ((getmntent(fp, &mentbuf)) == 0) {
Packit Service 569379
		/* TODO: Is this check reliable? */
Packit Service 569379
		if (stat(mentbuf.mnt_special, &st) == 0 && (st.st_mode & S_IFCHR)) {
Packit Service 569379
Packit Service 569379
			if (i >= lfs->cnt) {
Packit Service 569379
				lfs->cnt += DEVID_ARRAY_ADD;
Packit Service 569379
				lfs->ids = realloc(lfs->ids, sizeof(dev_t) * lfs->cnt);
Packit Service 569379
			}
Packit Service 569379
Packit Service 569379
			memcpy(&(lfs->ids[i++]), &st.st_dev, sizeof(dev_t));
Packit Service 569379
		}
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	fclose(fp);
Packit Service 569379
Packit Service 569379
	lfs->ids = realloc(lfs->ids, sizeof(dev_t) * i);
Packit Service 569379
	lfs->cnt = (lfs->ids == NULL ? 0 : i);
Packit Service 569379
Packit Service 569379
	return (lfs);
Packit Service 569379
}
Packit Service 569379
#endif
Packit Service 569379
Packit Service 569379
fsdev_t *fsdev_init()
Packit Service 569379
{
Packit Service 569379
	fsdev_t *lfs;
Packit Service 569379
Packit Service 569379
	lfs = malloc(sizeof(fsdev_t));
Packit Service 569379
Packit Service 569379
	if (lfs == NULL)
Packit Service 569379
		return (NULL);
Packit Service 569379
Packit Service 569379
	if (__fsdev_init(lfs) == NULL)
Packit Service 569379
		return (NULL);
Packit Service 569379
Packit Service 569379
        if (lfs->ids != NULL && lfs->cnt > 1)
Packit Service 569379
                qsort(lfs->ids, lfs->cnt, sizeof(dev_t), fsdev_cmp);
Packit Service 569379
Packit Service 569379
	return (lfs);
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
static inline int isfschar(int c)
Packit Service 569379
{
Packit Service 569379
	return (isalpha(c) || isdigit(c) || c == '-' || c == '_');
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
void fsdev_free(fsdev_t * lfs)
Packit Service 569379
{
Packit Service 569379
	if (lfs != NULL) {
Packit Service 569379
		free(lfs->ids);
Packit Service 569379
		free(lfs);
Packit Service 569379
	}
Packit Service 569379
	return;
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
int fsdev_search(fsdev_t * lfs, void *id)
Packit Service 569379
{
Packit Service 569379
	uint16_t w, s;
Packit Service 569379
	int cmp;
Packit Service 569379
Packit Service 569379
	if (!lfs)
Packit Service 569379
		return 1;
Packit Service 569379
Packit Service 569379
	w = lfs->cnt;
Packit Service 569379
	s = 0;
Packit Service 569379
Packit Service 569379
	while (w > 0) {
Packit Service 569379
		cmp = fsdev_cmp(id, &(lfs->ids[s + w / 2]));
Packit Service 569379
		if (cmp > 0) {
Packit Service 569379
			s += w / 2 + 1;
Packit Service 569379
			w = w - w / 2 - 1;
Packit Service 569379
		} else if (cmp < 0) {
Packit Service 569379
			w = w / 2;
Packit Service 569379
		} else {
Packit Service 569379
			return (1);
Packit Service 569379
		}
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	return (0);
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
int fsdev_path(fsdev_t * lfs, const char *path)
Packit Service 569379
{
Packit Service 569379
	struct stat st;
Packit Service 569379
Packit Service 569379
	if (stat(path, &st) != 0)
Packit Service 569379
		return (-1);
Packit Service 569379
Packit Service 569379
	return fsdev_search(lfs, &st.st_dev);
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
int fsdev_fd(fsdev_t * lfs, int fd)
Packit Service 569379
{
Packit Service 569379
	struct stat st;
Packit Service 569379
Packit Service 569379
	if (fstat(fd, &st) != 0)
Packit Service 569379
		return (-1);
Packit Service 569379
Packit Service 569379
	return fsdev_search(lfs, &st.st_dev);
Packit Service 569379
}