Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 May 2009 18:01:13 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 163184 for review
Message-ID:  <200905311801.n4VI1DKm016109@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163184

Change 163184 by trasz@trasz_victim on 2009/05/31 18:01:07

	Put limits set via rlimit(2) into hrl.

Affected files ...

.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#2 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#2 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#3 edit
.. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#3 edit

Differences ...

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#2 (text+ko) ====

@@ -32,22 +32,85 @@
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/priv.h>
+#include <sys/proc.h>
 #include <sys/sysent.h>
 #include <sys/sysproto.h>
 #include <sys/systm.h>
 #include <sys/types.h>
+#include <sys/eventhandler.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
 
 MALLOC_DEFINE(M_HRL, "hrl", "Hierarchical Resource Limits");
 
 /*
- * XXX: Locking.
+ * XXX: Need a better way to store stuff; rbtree?
  */
-static struct hrl_limit **limits = NULL;
+static struct hrl_limit *limits = NULL;
 static int nlimits = 0;
+static struct mtx hrllock;
+
+static void hrl_init(void);
+SYSINIT(hrl, SI_SUB_RUN_SCHEDULER, SI_ORDER_SECOND, hrl_init, NULL);
+
+int
+hrl_alloc(int object, uint64_t amount)
+{
+
+	KASSERT(amount > 0, ("invalid amount"));
+
+	return (0);
+}
+
+void
+hrl_free(int object, uint64_t amount)
+{
+
+	KASSERT(amount > 0, ("invalid amount"));
+}
+
+void
+hrl_adjust(int subject, id_t subject_id, int per, int object, int action, int64_t amount)
+{
+	mtx_lock(&hrllock);
+
+	nlimits++;
+	/*
+	 * XXX: Make it possible to remove and overwrite limits, not just add them.
+	 */
+	limits = realloc(limits, sizeof(struct hrl_limit) * nlimits, M_HRL, M_WAITOK);
+
+	limits[nlimits - 1].hl_subject = subject;
+	limits[nlimits - 1].hl_subject_id = subject_id;
+	limits[nlimits - 1].hl_per = per;
+	limits[nlimits - 1].hl_object = object;
+	limits[nlimits - 1].hl_action = action;
+	limits[nlimits - 1].hl_amount = amount;
+
+	mtx_unlock(&hrllock);
+}
+
+/*
+ * System calls.
+ */
 
 static int
-hrl_check(struct hrl_limit **limits, int nlimits)
+hrl_check(struct hrl_limit *limits, int nlimits)
 {
+	int i;
+
+	for (i = 0; i < nlimits; i++) {
+		if (limits[i].hl_subject <= 0 || limits[i].hl_subject > HRL_SUBJECT_MAX)
+			return (EINVAL);
+		if (limits[i].hl_per <= 0 || limits[i].hl_per > HRL_SUBJECT_MAX)
+			return (EINVAL);
+		if (limits[i].hl_object <= 0 || limits[i].hl_object > HRL_OBJECT_MAX)
+			return (EINVAL);
+		if (limits[i].hl_action <= 0 || limits[i].hl_action > HRL_ACTION_MAX)
+			return (EINVAL);
+		if (limits[i].hl_amount <= 0)
+			return (EINVAL);
+	}
 
 	return (0);
 }
@@ -57,7 +120,7 @@
 {
 	int error;
 	size_t buflen;
-	struct hrl_limit **newlimits;
+	struct hrl_limit *newlimits;
 
 	error = priv_check(td, PRIV_HRL_GET);
 	if (error)
@@ -74,9 +137,11 @@
 	 * Removing all the limits?
 	 */
 	if (uap->nentries == 0) {
+		mtx_lock(&hrllock);
 		free(limits, M_HRL);
 		limits = NULL;
 		nlimits = 0;
+		mtx_unlock(&hrllock);
 
 		return (0);
 	}
@@ -92,12 +157,16 @@
 	if (error)
 		goto out;
 
+	mtx_lock(&hrllock);
+
 	if (limits != NULL)
 		free(limits, M_HRL);
 
 	limits = newlimits;
 	nlimits = uap->nentries;
 
+	mtx_unlock(&hrllock);
+
 	return (0);
 
 out:
@@ -119,17 +188,48 @@
 	 * XXX: Check for being in jail?
 	 */
 
-	if (suword(uap->required, nlimits) != 0)
-		return (EINVAL);
+	mtx_lock(&hrllock);
+
+	if (suword(uap->required, nlimits) != 0) {
+		error = EINVAL;
+		goto out;
+	}
+
+	if (uap->nentries == 0 && uap->bufp == NULL) {
+		error = 0;
+		goto out;
+	}
 
-	if (uap->nentries == 0 && uap->bufp == NULL)
-		return (0);
+	if (uap->nentries < nlimits) {
+		error = EFBIG;
+		goto out;
+	}
 
-	if (uap->nentries < nlimits)
-		return (EFBIG);
+	if (nlimits == 0) {
+		error = 0;
+		goto out;
+	}
 
 	buflen = sizeof(struct hrl_limit) * nlimits;
 	error = copyout(limits, uap->bufp, buflen);
 
+out:
+	mtx_unlock(&hrllock);
+
 	return (error);
 }
+
+static void
+hrl_proc_exit(void *arg __unused, struct proc *p)
+{
+	/*
+	 * XXX: Remove per-process limits here.
+	 */
+}
+
+static void
+hrl_init(void)
+{
+	mtx_init(&hrllock, "hrl lock", NULL, MTX_DEF);
+	EVENTHANDLER_REGISTER(process_exit, hrl_proc_exit, NULL, EVENTHANDLER_PRI_ANY);
+}

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#2 (text+ko) ====

@@ -43,6 +43,7 @@
 #include <sys/systm.h>
 #include <sys/sysproto.h>
 #include <sys/file.h>
+#include <sys/hrl.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -642,6 +643,82 @@
 		callout_reset(&p->p_limco, hz, lim_cb, p);
 }
 
+static void
+hrl_handle_setrlimit(u_int which, struct rlimit *lim, struct thread *td)
+{
+	int object, subject, soft_action, hard_action;
+	id_t id;
+
+	/*
+	 * XXX: Locking.
+	 */
+	subject = HRL_SUBJECT_PROCESS;
+	id = td->td_proc->p_pid;
+	soft_action = HRL_ACTION_LOG;
+	hard_action = HRL_ACTION_DENY;
+
+	switch (which) {
+	case RLIMIT_CPU:
+		object = HRL_OBJECT_CPUTIME;
+		soft_action = HRL_ACTION_SIGXCPU;
+		break;
+	case RLIMIT_FSIZE:
+		object = HRL_OBJECT_FILESIZE;
+		break;
+	case RLIMIT_DATA:
+		object = HRL_OBJECT_DATASIZE;
+		break;
+	case RLIMIT_STACK:
+		object = HRL_OBJECT_STACKSIZE;
+		soft_action = HRL_ACTION_SIGSEGV;
+		break;
+	case RLIMIT_CORE:
+		object = HRL_OBJECT_COREDUMPSIZE;
+		break;
+	case RLIMIT_RSS:
+		object = HRL_OBJECT_MEMORYUSE;
+		break;
+	case RLIMIT_MEMLOCK:
+		object = HRL_OBJECT_MEMORYLOCKED;
+		break;
+	case RLIMIT_NPROC:
+		object = HRL_OBJECT_MAXPROCESSES;
+		subject = HRL_SUBJECT_USER;
+		id = td->td_ucred->cr_uid;
+		break;
+	case RLIMIT_NOFILE:
+		object = HRL_OBJECT_OPENFILES;
+		soft_action = HRL_ACTION_SIGXFSZ;
+		break;
+	case RLIMIT_SBSIZE:
+		object = HRL_OBJECT_SBSIZE;
+		subject = HRL_SUBJECT_USER;
+		id = td->td_ucred->cr_uid;
+		break;
+	case RLIMIT_VMEM:
+		object = HRL_OBJECT_VMEMORYUSE;
+		break;
+	case RLIMIT_NPTS:
+		object = HRL_OBJECT_PTY;
+		subject = HRL_SUBJECT_USER;
+		id = td->td_ucred->cr_uid;
+		break;
+	default:
+		panic("hrl_handle_setrlimit: unknown limit");
+	}
+
+	if (lim->rlim_cur != RLIM_INFINITY)
+		hrl_adjust(subject, id, subject, object, soft_action,
+		    lim->rlim_cur);
+	else
+		hrl_adjust(subject, id, subject, object, soft_action, 0);
+	if (lim->rlim_max != RLIM_INFINITY)
+		hrl_adjust(subject, id, subject, object, hard_action,
+		    lim->rlim_max);
+	else
+		hrl_adjust(subject, id, subject, object, hard_action, 0);
+}
+
 int
 kern_setrlimit(td, which, limp)
 	struct thread *td;
@@ -763,6 +840,8 @@
 		}
 	}
 
+	hrl_handle_setrlimit(which, alimp, td);
+
 	return (0);
 }
 

==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#3 (text+ko) ====

@@ -45,7 +45,6 @@
 	int64_t	hl_amount;
 };
 
-#define	HRL_SUBJECT_UNDEFINED	0x0000
 #define	HRL_SUBJECT_PROCESS	0x0001
 #define	HRL_SUBJECT_USER	0x0002
 #define	HRL_SUBJECT_GROUP	0x0003
@@ -57,7 +56,6 @@
  * 'hl_per' takes the same flags as 'hl_subject'.
  */
 
-#define	HRL_OBJECT_UNDEFINED	0x0000
 #define	HRL_OBJECT_CPUTIME	0x0001
 #define	HRL_OBJECT_FILESIZE	0x0002
 #define	HRL_OBJECT_DATASIZE	0x0003
@@ -72,27 +70,31 @@
 #define	HRL_OBJECT_PTY		0x000c
 #define	HRL_OBJECT_MAX		HRL_OBJECT_PTY
 
-#define	HRL_ACTION_UNDEFINED	0x0000
 #define	HRL_ACTION_DENY		0x0001
 #define	HRL_ACTION_DELAY	0x0002
 #define	HRL_ACTION_LOG		0x0003
 #define	HRL_ACTION_SIGHUP	0x0004
 #define	HRL_ACTION_SIGINT	0x0005
 #define	HRL_ACTION_SIGKILL	0x0006
-#define	HRL_ACTION_SIGXCPU	0x0007
-#define	HRL_ACTION_SIGXFSZ	0x0008
+#define	HRL_ACTION_SIGSEGV	0x0007
+#define	HRL_ACTION_SIGXCPU	0x0008
+#define	HRL_ACTION_SIGXFSZ	0x0009
 #define	HRL_ACTION_MAX		HRL_ACTION_SIGXFSZ
 
 #define	HRL_MAX_LIMITS		128
 
-int	hrl_alloc(int tag, int amount);
-void	hrl_free(int tag, int amount);
+#ifdef _KERNEL
+
+int	hrl_alloc(int object, uint64_t amount);
+void	hrl_free(int object, uint64_t amount);
+
+void	hrl_adjust(int subject, id_t subject_id, int per, int object, int action, int64_t amount);
 
-#ifndef _KERNEL
+#else /* !_KERNEL */
 
 __BEGIN_DECLS
-int	hrl_get(struct hrl_limit **bufp, int nentries, int *count);
-int	hrl_set(struct hrl_limit **bufp, int nentries);
+int	hrl_get(struct hrl_limit *bufp, int nentries, int *count);
+int	hrl_set(struct hrl_limit *bufp, int nentries);
 __END_DECLS
 
 #endif /* !_KERNEL */

==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#3 (text+ko) ====

@@ -30,21 +30,33 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
 #include <sys/hrl.h>
 
 static void
 print_subject(int subject, id_t id)
 {
+	struct passwd *pwd;
+	struct group *grp;
 
 	switch (subject) {
 	case HRL_SUBJECT_PROCESS:
 		printf("process:%u", (unsigned int)id);
 		break;
 	case HRL_SUBJECT_USER:
-		printf("user:%u", (unsigned int)id);
+		pwd = getpwuid(id);
+		if (pwd != NULL)
+			printf("user:%s", pwd->pw_name);
+		else
+			printf("user:%u", (unsigned int)id);
 		break;
 	case HRL_SUBJECT_GROUP:
-		printf("group:%u", (unsigned int)id);
+		grp = getgrgid(id);
+		if (grp != NULL)
+			printf("group:%s", grp->gr_name);
+		else
+			printf("group:%u", (unsigned int)id);
 		break;
 	case HRL_SUBJECT_LOGINCLASS:
 		printf("class:%u", (unsigned int)id);
@@ -127,6 +139,9 @@
 	case HRL_ACTION_SIGKILL:
 		printf("sigkill");
 		break;
+	case HRL_ACTION_SIGSEGV:
+		printf("sigsegv");
+		break;
 	case HRL_ACTION_SIGXCPU:
 		printf("sigxcpu");
 		break;
@@ -168,7 +183,7 @@
 main(int argc __unused, char **argv __unused)
 {
 	int error, nentries, i;
-	struct hrl_limit **limits;
+	struct hrl_limit *limits;
 
 	error = hrl_get(NULL, 0, &nentries);
 	if (error)
@@ -190,16 +205,16 @@
 	printf("Defined resource limits:\n");
 
 	for (i = 0; i < nentries; i++) {
-		print_subject(limits[i]->hl_subject, limits[i]->hl_subject_id);
+		print_subject(limits[i].hl_subject, limits[i].hl_subject_id);
 		printf(":");
-		print_object(limits[i]->hl_object);
+		print_object(limits[i].hl_object);
 		printf(":");
-		print_action(limits[i]->hl_action);
+		print_action(limits[i].hl_action);
 		printf(":");
-		printf("%jd", limits[i]->hl_amount);
-		if (limits[i]->hl_subject != limits[i]->hl_per) {
+		printf("%jd", limits[i].hl_amount);
+		if (limits[i].hl_subject != limits[i].hl_per) {
 			printf("/");
-			print_per(limits[i]->hl_per);
+			print_per(limits[i].hl_per);
 		}
 		printf("\n");
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905311801.n4VI1DKm016109>