Page MenuHomeFreeBSD

D55039.diff
No OneTemporary

D55039.diff

diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -475,6 +475,7 @@
typedef int (__sys_pdrfork_t)(int *, int, int);
typedef int (__sys_pdwait_t)(int, int *, int, struct __wrusage *, struct __siginfo *);
typedef int (__sys_renameat2_t)(int, const char *, int, const char *, int);
+typedef int (__sys_setrlimit_uid_t)(u_int, struct rlimit *, uid_t);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -885,6 +886,7 @@
int __sys_pdrfork(int * fdp, int pdflags, int rfflags);
int __sys_pdwait(int fd, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info);
int __sys_renameat2(int oldfd, const char * old, int newfd, const char * new, int flags);
+int __sys_setrlimit_uid(u_int which, struct rlimit * rlp, uid_t uid);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/getrlimit.2 b/lib/libsys/getrlimit.2
--- a/lib/libsys/getrlimit.2
+++ b/lib/libsys/getrlimit.2
@@ -30,7 +30,8 @@
.Os
.Sh NAME
.Nm getrlimit ,
-.Nm setrlimit
+.Nm setrlimit ,
+.Nm setrlimit_uid
.Nd control maximum system resource consumption
.Sh LIBRARY
.Lb libc
@@ -42,6 +43,7 @@
.Fn getrlimit "int resource" "struct rlimit *rlp"
.Ft int
.Fn setrlimit "int resource" "const struct rlimit *rlp"
+.Fn setrlimit_uid "int resource" "const struct rlimit *rlp" "uid_t uid"
.Sh DESCRIPTION
Limits on the consumption of system resources by the current process
and each process it creates may be obtained with the
@@ -50,6 +52,13 @@
.Fn setrlimit
system call.
.Pp
+Limits on the consumption of system resources for a specific UID
+and each process it creates may be obtained with the
+.Fn getrlimit
+system call, and set with the
+.Fn setrlimit_uid
+system call.
+.Pp
The
.Fa resource
argument is one of the following:
@@ -169,6 +178,20 @@
.Ic limit
is thus a built-in command to
.Xr csh 1 .
+This does not apply to the limits which are tracked globally for each user.
+These per-UID limits are:
+.Bl -dash -compact
+.It
+RLIMIT_KQUEUES
+.It
+RLIMIT_NPROC
+.It
+RLIMIT_NPTS
+.It
+RLIMIT_UMTXP
+.It
+RLIMIT_VMM
+.El
.Pp
The system refuses to extend the data or stack space when the limits
would be exceeded in the normal way: a
@@ -226,6 +249,17 @@
.Fn setrlimit
would have
raised the maximum limit value, and the caller is not the super-user.
+.It Bq Er EPERM
+The caller attempted to change a per-UID limit using
+.Fn setrlimit_uid
+and was not the super-user.
+.It Bq Er ENOENT
+The caller attempted to change a per-UID limit using
+.Fn setrlimit_uid
+and there are no active sessions for the request UID.
+.It Bq Er EINVAL
+The caller attempted to change a per-process limit using
+.Fn setrlimit_uid .
.El
.Sh SEE ALSO
.Xr csh 1 ,
@@ -242,8 +276,15 @@
.Fn setrlimit
functions are expected to conform to
.St -p1003.1-2001 .
+Per-UID limits and the
+.Fn setrlimit_uid
+function are non-standard.
.Sh HISTORY
The
.Fn getrlimit
system call appeared in
.Bx 4.2 .
+The
+.Fn setrlimit_uid
+system call appeared in
+.Fx 16.0 .
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -825,4 +825,6 @@
__sys_pdwait;
_renameat2;
__sys_renameat2;
+ _setrlimit_uid;
+ __sys_setrlimit_uid;
};
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -665,6 +665,7 @@
#define AUE_SETCRED 43271 /* FreeBSD-specific. */
#define AUE_INOTIFY 43272 /* FreeBSD/Linux. */
#define AUE_PDRFORK 43273 /* FreeBSD-specific. */
+#define AUE_SETRLIMIT_UID 43274 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -520,4 +520,5 @@
#define FREEBSD32_SYS_pdrfork 600
#define FREEBSD32_SYS_freebsd32_pdwait 601
#define FREEBSD32_SYS_renameat2 602
-#define FREEBSD32_SYS_MAXSYSCALL 603
+#define FREEBSD32_SYS_setrlimit_uid 603
+#define FREEBSD32_SYS_MAXSYSCALL 604
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -608,4 +608,5 @@
"pdrfork", /* 600 = pdrfork */
"freebsd32_pdwait", /* 601 = freebsd32_pdwait */
"renameat2", /* 602 = renameat2 */
+ "setrlimit_uid", /* 603 = setrlimit_uid */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -670,4 +670,5 @@
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(freebsd32_pdwait_args), .sy_call = (sy_call_t *)freebsd32_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = freebsd32_pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
+ { .sy_narg = AS(setrlimit_uid_args), .sy_call = (sy_call_t *)sys_setrlimit_uid, .sy_auevent = AUE_SETRLIMIT_UID, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = setrlimit_uid */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3458,6 +3458,15 @@
*n_args = 5;
break;
}
+ /* setrlimit_uid */
+ case 603: {
+ struct setrlimit_uid_args *p = params;
+ uarg[a++] = p->which; /* u_int */
+ uarg[a++] = (intptr_t)p->rlp; /* struct rlimit * */
+ uarg[a++] = p->uid; /* uid_t */
+ *n_args = 3;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9347,6 +9356,22 @@
break;
};
break;
+ /* setrlimit_uid */
+ case 603:
+ switch (ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "userland struct rlimit *";
+ break;
+ case 2:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11280,6 +11305,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* setrlimit_uid */
+ case 603:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -669,4 +669,5 @@
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(pdwait_args), .sy_call = (sy_call_t *)sys_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
+ { .sy_narg = AS(setrlimit_uid_args), .sy_call = (sy_call_t *)sys_setrlimit_uid, .sy_auevent = AUE_SETRLIMIT_UID, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = setrlimit_uid */
};
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -55,6 +55,7 @@
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <sys/umtxvar.h>
#include <vm/vm.h>
@@ -654,7 +655,7 @@
case RLIMIT_NPTS:
case RLIMIT_PIPEBUF:
case RLIMIT_UMTXP:
- case RLIMIT_VMM:
+ case RLIMIT_VMS:
return true;
default:
return false;
@@ -940,6 +941,66 @@
error = copyout(&res, uap->res, sizeof(res));
return (error);
}
+#ifndef _SYS_SYSPROTO_H_
+struct setrlimit_uid_args {
+ u_int which;
+ struct rlimit *rlp;
+ uid_t uid;
+};
+#endif
+int
+sys_setrlimit_uid(struct thread *td, struct setrlimit_uid_args *uap)
+{
+ struct rlimit alim;
+ int error;
+
+ if ((error = copyin(uap->rlp, &alim, sizeof(struct rlimit))))
+ return (error);
+ return (kern_setrlimit_uid(td, uap->which, &alim, uap->uid));
+}
+
+int
+kern_setrlimit_uid(struct thread *td, u_int which, struct rlimit *limp, uid_t uid)
+{
+ struct rlimit *alimp;
+ struct uidinfo *ui;
+ int error;
+
+ if (which >= RLIM_NLIMITS || !rlim_is_per_uid(which))
+ return (EINVAL);
+
+ /* Preserve 'setrlimit' bugs. */
+ if (limp->rlim_cur < 0)
+ limp->rlim_cur = RLIM_INFINITY;
+ if (limp->rlim_max < 0)
+ limp->rlim_max = RLIM_INFINITY;
+
+ ui = uifind(uid);
+ if (ui == NULL)
+ return (ENOENT);
+
+ /*
+ * Allow a calling process owned by 'uid' to lower the per-UID limit.
+ */
+ if (td->td_ucred->cr_uid != uid &&
+ (error = priv_check(td, PRIV_PROC_SETRLIMIT_UID)))
+ return (error);
+
+ mtx_lock(&ui->ui_limlock);
+ alimp = &ui->ui_limit->pl_rlimit[which];
+ if (limp->rlim_cur > alimp->rlim_max ||
+ limp->rlim_max > alimp->rlim_max)
+ if ((error = priv_check(td, PRIV_PROC_SETRLIMIT_UID))) {
+ mtx_unlock(&ui->ui_limlock);
+ return (error);
+ }
+ if (limp->rlim_cur > limp->rlim_max)
+ limp->rlim_cur = limp->rlim_max;
+ *alimp = *limp;
+ mtx_unlock(&ui->ui_limlock);
+
+ return (0);
+}
/*
* Transform the running time and tick information for children of proc p
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -608,4 +608,5 @@
"pdrfork", /* 600 = pdrfork */
"pdwait", /* 601 = pdwait */
"renameat2", /* 602 = renameat2 */
+ "setrlimit_uid", /* 603 = setrlimit_uid */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3429,4 +3429,11 @@
int flags
);
}
+603 AUE_SETRLIMIT_UID STD|CAPENABLED {
+ int setrlimit_uid(
+ u_int which,
+ _In_ struct rlimit *rlp,
+ uid_t uid
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3555,6 +3555,15 @@
*n_args = 5;
break;
}
+ /* setrlimit_uid */
+ case 603: {
+ struct setrlimit_uid_args *p = params;
+ uarg[a++] = p->which; /* u_int */
+ uarg[a++] = (intptr_t)p->rlp; /* struct rlimit * */
+ uarg[a++] = p->uid; /* uid_t */
+ *n_args = 3;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9521,6 +9530,22 @@
break;
};
break;
+ /* setrlimit_uid */
+ case 603:
+ switch (ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "userland struct rlimit *";
+ break;
+ case 2:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11549,6 +11574,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* setrlimit_uid */
+ case 603:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/sys/param.h b/sys/sys/param.h
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -110,6 +110,7 @@
#define P_OSREL_TLSBASE 1500044
#define P_OSREL_EXTERRCTL 1500045
#define P_OSREL_AMD64_TF_FRED 1600014
+#define P_OSREL_SETRLIMIT_UID 1600018
#define P_OSREL_MAJOR(x) ((x) / 100000)
#endif
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -162,6 +162,7 @@
#define PRIV_PROC_SETLOGIN 161 /* Can call setlogin. */
#define PRIV_PROC_SETRLIMIT 162 /* Can raise resources limits. */
#define PRIV_PROC_SETLOGINCLASS 163 /* Can call setloginclass(2). */
+#define PRIV_PROC_SETRLIMIT_UID 164 /* Can call setrlimit_uid(2). */
/*
* System V IPC privileges.
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -41,6 +41,11 @@
#define _ID_T_DECLARED
#endif
+#ifndef _UID_T_DECLARED
+typedef __uid_t uid_t;
+#define _UID_T_DECLARED
+#endif
+
#ifndef _RLIM_T_DECLARED
typedef __rlim_t rlim_t;
#define _RLIM_T_DECLARED
@@ -192,6 +197,7 @@
int getrusage(int, struct rusage *);
int setpriority(int, int, int);
int setrlimit(int, const struct rlimit *);
+int setrlimit_uid(int, const struct rlimit *, uid_t);
#if __BSD_VISIBLE
int getrlimitusage(unsigned which, int flags, rlim_t *res);
#endif
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -541,4 +541,5 @@
#define SYS_pdrfork 600
#define SYS_pdwait 601
#define SYS_renameat2 602
-#define SYS_MAXSYSCALL 603
+#define SYS_setrlimit_uid 603
+#define SYS_MAXSYSCALL 604
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -444,4 +444,5 @@
kexec_load.o \
pdrfork.o \
pdwait.o \
- renameat2.o
+ renameat2.o \
+ setrlimit_uid.o
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -331,6 +331,7 @@
struct itimerval *);
int kern_setpriority(struct thread *td, int which, int who, int prio);
int kern_setrlimit(struct thread *, u_int, struct rlimit *);
+int kern_setrlimit_uid(struct thread *, u_int, struct rlimit *, uid_t);
int kern_setsockopt(struct thread *td, int s, int level, int name,
const void *optval, enum uio_seg valseg, socklen_t valsize);
int kern_settimeofday(struct thread *td, struct timeval *tv,
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1932,6 +1932,11 @@
char new_l_[PADL_(const char *)]; const char * new; char new_r_[PADR_(const char *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
+struct setrlimit_uid_args {
+ char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)];
+ char rlp_l_[PADL_(struct rlimit *)]; struct rlimit * rlp; char rlp_r_[PADR_(struct rlimit *)];
+ char uid_l_[PADL_(uid_t)]; uid_t uid; char uid_r_[PADR_(uid_t)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2342,6 +2347,7 @@
int sys_pdrfork(struct thread *, struct pdrfork_args *);
int sys_pdwait(struct thread *, struct pdwait_args *);
int sys_renameat2(struct thread *, struct renameat2_args *);
+int sys_setrlimit_uid(struct thread *, struct setrlimit_uid_args *);
#ifdef COMPAT_43
@@ -3344,6 +3350,7 @@
#define SYS_AUE_pdrfork AUE_PDRFORK
#define SYS_AUE_pdwait AUE_PDWAIT
#define SYS_AUE_renameat2 AUE_RENAMEAT
+#define SYS_AUE_setrlimit_uid AUE_SETRLIMIT_UID
#undef PAD_
#undef PADL_

File Metadata

Mime Type
text/plain
Expires
Wed, May 20, 1:29 PM (6 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33348561
Default Alt Text
D55039.diff (14 KB)

Event Timeline