Subject: Re: core file name format: diffs
To: der Mouse <mouse@Rodents.Montreal.QC.CA>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 09/26/1999 19:49:39
--yrj/dFKFPuw6o+aM
Content-Type: text/plain; charset=us-ascii
On Fri, Sep 24, 1999 at 11:55:44PM -0400, der Mouse wrote:
> Um, you need to not just pool_put, but also free
> p->p_limit->pl_corename if it's not defcorename.
Rigth.
> Since this makes two
> places that do basically the same thing (free a p_limit if its refcount
> is zero) perhaps a routine to do this should be created?
Well, as enami pointed out there is a limfree() routine, which is
local to kern_resources.h, and would be suited for this.
I made it global and use it at appropriate place (i.e each time we need to
decrease a ref count). New diffs attached.
--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel.Bouyer@lip6.fr
--
--yrj/dFKFPuw6o+aM
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sysctl.diff5"
Index: sys/proc.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/proc.h,v
retrieving revision 1.83
diff -u -r1.83 proc.h
--- proc.h 1999/08/10 23:33:27 1.83
+++ proc.h 1999/09/26 17:44:09
@@ -392,5 +392,6 @@
void proclist_unlock_read __P((void));
int proclist_lock_write __P((void));
void proclist_unlock_write __P((int));
+void p_sugid __P((struct proc*));
#endif /* _KERNEL */
#endif /* !_SYS_PROC_H_ */
Index: sys/resource.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/resource.h,v
retrieving revision 1.19
diff -u -r1.19 resource.h
--- resource.h 1998/12/09 14:39:09 1.19
+++ resource.h 1999/09/26 17:44:09
@@ -120,7 +120,8 @@
#ifdef _KERNEL
extern struct loadavg averunnable;
-int dosetrlimit __P((struct proc *, int, struct rlimit *));
+struct pcred;
+int dosetrlimit __P((struct proc *, struct pcred *, int, struct rlimit *));
int donice __P((struct proc *, struct proc *, int));
#else
Index: sys/resourcevar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/resourcevar.h,v
retrieving revision 1.13
diff -u -r1.13 resourcevar.h
--- resourcevar.h 1998/03/01 02:24:14 1.13
+++ resourcevar.h 1999/09/26 17:44:10
@@ -73,6 +73,7 @@
*/
struct plimit {
struct rlimit pl_rlimit[RLIM_NLIMITS];
+ char *pl_corename;
#define PL_SHAREMOD 0x01 /* modifications are shared */
int p_lflags;
int p_refcnt; /* number of references */
@@ -88,8 +89,8 @@
void addupc_task __P((struct proc *p, u_long pc, u_int ticks));
void calcru __P((struct proc *p, struct timeval *up, struct timeval *sp,
struct timeval *ip));
-struct plimit
- *limcopy __P((struct plimit *lim));
+struct plimit *limcopy __P((struct plimit *lim));
+void limfree __P((struct plimit *));
void ruadd __P((struct rusage *ru, struct rusage *ru2));
#endif
#endif /* !_SYS_RESOURCEVAR_H_ */
Index: sys/sysctl.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/sysctl.h,v
retrieving revision 1.35
diff -u -r1.35 sysctl.h
--- sysctl.h 1999/06/24 14:18:12 1.35
+++ sysctl.h 1999/09/26 17:44:10
@@ -92,7 +92,8 @@
#define CTL_MACHDEP 7 /* machine dependent */
#define CTL_USER 8 /* user-level */
#define CTL_DDB 9 /* in-kernel debugger */
-#define CTL_MAXID 10 /* number of valid top-level ids */
+#define CTL_PROC 10 /* per-proc attr */
+#define CTL_MAXID 11 /* number of valid top-level ids */
#define CTL_NAMES { \
{ 0, 0 }, \
@@ -105,6 +106,7 @@
{ "machdep", CTLTYPE_NODE }, \
{ "user", CTLTYPE_NODE }, \
{ "ddb", CTLTYPE_NODE }, \
+ { "proc", CTLTYPE_NODE }, \
}
/*
@@ -145,7 +147,7 @@
#define KERN_SYSVMSG 33 /* int: SysV message queue suppoprt */
#define KERN_SYSVSEM 34 /* int: SysV semaphore support */
#define KERN_SYSVSHM 35 /* int: SysV shared memory support */
-#define KERN_SHORTCORENAME 36 /* int: programs dump core as "core" */
+#define KERN_DEFCORENAME 36 /* string: default corename format */
#define KERN_SYNCHRONIZED_IO 37 /* int: POSIX synchronized I/O */
#define KERN_IOV_MAX 38 /* int: max iovec's for readv(2) etc. */
#define KERN_MBUF 39 /* node: mbuf parameters */
@@ -192,7 +194,7 @@
{ "sysvmsg", CTLTYPE_INT }, \
{ "sysvsem", CTLTYPE_INT }, \
{ "sysvshm", CTLTYPE_INT }, \
- { "shortcorename", CTLTYPE_INT }, \
+ { "defcorename", CTLTYPE_STRING }, \
{ "synchronized_io", CTLTYPE_INT }, \
{ "iov_max", CTLTYPE_INT }, \
{ "mbuf", CTLTYPE_NODE }, \
@@ -356,6 +358,61 @@
#define CTL_DEBUG_VALUE 1 /* int: variable value */
#define CTL_DEBUG_MAXID 20
+/*
+ * CTL_PROC subtype. Either a PID, or a magic value for the current proc.
+ */
+
+#define PROC_CURPROC (~((u_int)1 << 31))
+
+/*
+ * CTL_PROC tree: either corename (string), or a limit
+ * (rlimit.<type>.{hard,soft}, int).
+ */
+#define PROC_PID_CORENAME 1
+#define PROC_PID_LIMIT 2
+#define PROC_PID_MAXID 3
+
+#define PROC_PID_NAMES { \
+ { 0, 0 }, \
+ { "corename", CTLTYPE_STRING }, \
+ { "rlimit", CTLTYPE_NODE }, \
+}
+
+/* Limit types from <sys/resources.h> */
+#define PROC_PID_LIMIT_CPU (RLIMIT_CPU+1)
+#define PROC_PID_LIMIT_FSIZE (RLIMIT_FSIZE+1)
+#define PROC_PID_LIMIT_DATA (RLIMIT_DATA+1)
+#define PROC_PID_LIMIT_STACK (RLIMIT_STACK+1)
+#define PROC_PID_LIMIT_CORE (RLIMIT_CORE+1)
+#define PROC_PID_LIMIT_RSS (RLIMIT_RSS+1)
+#define PROC_PID_LIMIT_MEMLOCK (RLIMIT_MEMLOCK+1)
+#define PROC_PID_LIMIT_NPROC (RLIMIT_NPROC+1)
+#define PROC_PID_LIMIT_NOFILE (RLIMIT_NOFILE+1)
+#define PROC_PID_LIMIT_MAXID 10
+
+#define PROC_PID_LIMIT_NAMES { \
+ { 0, 0 }, \
+ { "cputime", CTLTYPE_NODE }, \
+ { "filesize", CTLTYPE_NODE }, \
+ { "datasize", CTLTYPE_NODE }, \
+ { "stacksize", CTLTYPE_NODE }, \
+ { "coredumpsize", CTLTYPE_NODE }, \
+ { "memoryuse", CTLTYPE_NODE }, \
+ { "memorylocked", CTLTYPE_NODE }, \
+ { "maxproc", CTLTYPE_NODE }, \
+ { "descriptors", CTLTYPE_NODE }, \
+}
+/* for each type, either hard or soft value */
+#define PROC_PID_LIMIT_TYPE_SOFT 1
+#define PROC_PID_LIMIT_TYPE_HARD 2
+#define PROC_PID_LIMIT_TYPE_MAXID 3
+
+#define PROC_PID_LIMIT_TYPE_NAMES { \
+ {0, 0}, \
+ { "soft", CTLTYPE_QUAD }, \
+ { "hard", CTLTYPE_QUAD }, \
+}
+
#ifdef _KERNEL
/*
* CTL_DEBUG variables.
@@ -394,12 +451,14 @@
int sysctl_int __P((void *, size_t *, void *, size_t, int *));
int sysctl_rdint __P((void *, size_t *, void *, int));
+int sysctl_quad __P((void *, size_t *, void *, size_t, quad_t *));
+int sysctl_rdquad __P((void *, size_t *, void *, quad_t));
int sysctl_string __P((void *, size_t *, void *, size_t, char *, int));
int sysctl_rdstring __P((void *, size_t *, void *, char *));
int sysctl_rdstruct __P((void *, size_t *, void *, void *, int));
int sysctl_struct __P((void *, size_t *, void *, size_t, void *, int));
int sysctl_file __P((char *, size_t *));
-int sysctl_doproc __P((int *, u_int, char *, size_t *));
+int sysctl_doeproc __P((int *, u_int, char *, size_t *));
struct radix_node;
struct walkarg;
int sysctl_dumpentry __P((struct radix_node *, void *));
@@ -421,6 +480,8 @@
struct proc *));
int hw_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
struct proc *));
+int proc_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+ struct proc *));
#ifdef DEBUG
int debug_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
struct proc *));
Index: kern/init_main.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/init_main.c,v
retrieving revision 1.156
diff -u -r1.156 init_main.c
--- init_main.c 1999/09/17 20:11:56 1.156
+++ init_main.c 1999/09/26 17:44:10
@@ -182,6 +182,7 @@
#if defined(NFSSERVER) || defined(NFS)
extern void nfs_init __P((void));
#endif
+ extern char defcorename[];
/*
* Initialize the current process pointer (curproc) before
@@ -286,6 +287,7 @@
limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
+ limit0.pl_corename = defcorename;
limit0.p_refcnt = 1;
/*
Index: kern/kern_exec.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v
retrieving revision 1.102
diff -u -r1.102 kern_exec.c
--- kern_exec.c 1999/08/09 02:42:20 1.102
+++ kern_exec.c 1999/09/26 17:44:10
@@ -457,7 +457,7 @@
p->p_ucred->cr_uid = attr.va_uid;
if (attr.va_mode & S_ISGID)
p->p_ucred->cr_gid = attr.va_gid;
- p->p_flag |= P_SUGID;
+ p_sugid(p);
} else
p->p_flag &= ~P_SUGID;
p->p_cred->p_svuid = p->p_ucred->cr_uid;
Index: kern/kern_exit.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_exit.c,v
retrieving revision 1.73
diff -u -r1.73 kern_exit.c
--- kern_exit.c 1999/07/22 21:08:31 1.73
+++ kern_exit.c 1999/09/26 17:44:10
@@ -326,8 +326,7 @@
* Other substructures are freed from wait().
*/
curproc = NULL;
- if (--p->p_limit->p_refcnt == 0)
- pool_put(&plimit_pool, p->p_limit);
+ limfree(p->p_limit);
/*
* Finally, call machine-dependent code to switch to a new
Index: kern/kern_proc.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_proc.c,v
retrieving revision 1.34
diff -u -r1.34 kern_proc.c
--- kern_proc.c 1999/07/25 06:30:34 1.34
+++ kern_proc.c 1999/09/26 17:44:10
@@ -519,6 +519,30 @@
}
}
+/* mark process as suid/sgid, reset some values do defaults */
+void
+p_sugid(p)
+ struct proc *p;
+{
+ extern char defcorename[];
+ struct plimit *newlim;
+
+ p->p_flag |= P_SUGID;
+ /* reset what needs to be reset in plimit */
+ if (p->p_limit->pl_corename != defcorename) {
+ if (p->p_limit->p_refcnt > 1 &&
+ (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
+ newlim = limcopy(p->p_limit);
+ limfree(p->p_limit);
+ p->p_limit = newlim;
+ } else {
+ free(p->p_limit->pl_corename, M_TEMP);
+ }
+ p->p_limit->pl_corename = defcorename;
+ }
+}
+
+
#ifdef DEBUG
void
pgrpdump()
Index: kern/kern_prot.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_prot.c,v
retrieving revision 1.54
diff -u -r1.54 kern_prot.c
--- kern_prot.c 1999/04/30 05:30:32 1.54
+++ kern_prot.c 1999/09/26 17:44:10
@@ -335,7 +335,7 @@
pc->pc_ucred->cr_uid = uid;
pc->p_ruid = uid;
pc->p_svuid = uid;
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
@@ -363,7 +363,7 @@
*/
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_uid = euid;
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
@@ -408,7 +408,7 @@
}
if (euid != (uid_t)-1 && ruid != (uid_t)-1)
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
@@ -434,7 +434,7 @@
pc->pc_ucred->cr_gid = gid;
pc->p_rgid = gid;
pc->p_svgid = gid;
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
@@ -458,7 +458,7 @@
return (error);
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_gid = egid;
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
@@ -501,7 +501,7 @@
}
if (egid != (gid_t)-1 && rgid != (gid_t)-1)
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
@@ -531,7 +531,7 @@
if (error)
return (error);
pc->pc_ucred->cr_ngroups = ngrp;
- p->p_flag |= P_SUGID;
+ p_sugid(p);
return (0);
}
Index: kern/kern_resource.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_resource.c,v
retrieving revision 1.52
diff -u -r1.52 kern_resource.c
--- kern_resource.c 1999/07/25 06:30:34 1.52
+++ kern_resource.c 1999/09/26 17:44:11
@@ -56,7 +56,8 @@
#include <uvm/uvm_extern.h>
-void limfree __P((struct plimit *));
+extern char *defcorename;
+
/*
* Resource controls and accounting.
*/
@@ -225,17 +226,19 @@
error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
if (error)
return (error);
- return (dosetrlimit(p, which, &alim));
+ return (dosetrlimit(p, p->p_cred, which, &alim));
}
int
-dosetrlimit(p, which, limp)
+dosetrlimit(p, cred, which, limp)
struct proc *p;
+ struct pcred *cred;
int which;
struct rlimit *limp;
{
register struct rlimit *alimp;
extern unsigned maxdmap, maxsmap;
+ struct plimit *newplim;
int error;
if ((u_int)which >= RLIM_NLIMITS)
@@ -245,16 +248,22 @@
return (EINVAL);
alimp = &p->p_rlimit[which];
+ /* if we don't change the value, no need to limcopy() */
+ if (limp->rlim_cur == alimp->rlim_cur &&
+ limp->rlim_max == alimp->rlim_max)
+ return 0;
+
if (limp->rlim_cur > alimp->rlim_max ||
limp->rlim_max > alimp->rlim_max)
- if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ if ((error = suser(cred->pc_ucred, &p->p_acflag)) != 0)
return (error);
if (limp->rlim_cur > limp->rlim_max)
limp->rlim_cur = limp->rlim_max;
if (p->p_limit->p_refcnt > 1 &&
(p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
- p->p_limit->p_refcnt--;
- p->p_limit = limcopy(p->p_limit);
+ newplim = limcopy(p->p_limit);
+ limfree(p->p_limit);
+ p->p_limit = newplim;
alimp = &p->p_rlimit[which];
}
@@ -458,6 +467,13 @@
newlim = pool_get(&plimit_pool, PR_WAITOK);
memcpy(newlim->pl_rlimit, lim->pl_rlimit,
sizeof(struct rlimit) * RLIM_NLIMITS);
+ if (lim->pl_corename == defcorename) {
+ newlim->pl_corename = lim->pl_corename;
+ } else {
+ newlim->pl_corename = malloc(strlen(lim->pl_corename)+1,
+ M_TEMP, M_WAITOK);
+ strcpy(newlim->pl_corename, lim->pl_corename);
+ }
newlim->p_lflags = 0;
newlim->p_refcnt = 1;
return (newlim);
@@ -470,5 +486,7 @@
if (--lim->p_refcnt > 0)
return;
+ if (lim->pl_corename != defcorename)
+ free(lim->pl_corename, M_TEMP);
pool_put(&plimit_pool, lim);
}
Index: kern/kern_sig.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_sig.c,v
retrieving revision 1.93
diff -u -r1.93 kern_sig.c
--- kern_sig.c 1999/08/31 12:30:35 1.93
+++ kern_sig.c 1999/09/26 17:44:11
@@ -79,6 +79,7 @@
void stop __P((struct proc *p));
void killproc __P((struct proc *, char *));
+static int build_corename __P((char *));
sigset_t contsigmask, stopsigmask, sigcantmask;
@@ -1264,9 +1265,8 @@
struct nameidata nd;
struct vattr vattr;
int error, error1;
- char name[MAXCOMLEN+6]; /* progname.core */
+ char name[MAXPATHLEN];
struct core core;
- extern int shortcorename;
/*
* Make sure the process has not set-id, to prevent data leaks.
@@ -1293,11 +1293,10 @@
(vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0)
return (EPERM);
- if (shortcorename)
- sprintf(name, "core");
- else
- sprintf(name, "%s.core", p->p_comm);
-
+ error = build_corename(name);
+ if (error)
+ return error;
+
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
error = vn_open(&nd, O_CREAT | FWRITE | FNOSYMLINK, S_IRUSR | S_IWUSR);
if (error)
@@ -1393,4 +1392,52 @@
psignal(p, SIGSYS);
return (ENOSYS);
+}
+
+static int
+build_corename(dst)
+ char *dst;
+{
+ const char *s;
+ char *d;
+ int len, i;
+
+ for (s = curproc->p_limit->pl_corename, len = 0, d = dst;
+ *s != '\0'; s++) {
+ if (*s == '%') {
+ switch (*(s+1)) {
+ case 'n':
+ i = snprintf(d,MAXPATHLEN - 1 - len, "%s",
+ curproc->p_comm);
+ break;
+ case 'p':
+ i = snprintf(d, MAXPATHLEN - 1 - len, "%d",
+ curproc->p_pid);
+ break;
+ case 'u':
+ i = snprintf(d, MAXPATHLEN - 1 - len, "%s",
+ curproc->p_pgrp->pg_session->s_login);
+ break;
+ case 't':
+ i = snprintf(d, MAXPATHLEN - 1 - len, "%ld",
+ curproc->p_stats->p_start.tv_sec);
+ break;
+ default:
+ goto copy;
+ }
+ if (i >= MAXPATHLEN - 1 - len)
+ return ENAMETOOLONG;
+ len += i;
+ d += i;
+ s++;
+ } else {
+copy: *d = *s;
+ d++;
+ len++;
+ if (len >= MAXPATHLEN - 1)
+ return ENAMETOOLONG;
+ }
+ }
+ *d = '\0';
+ return 0;
}
Index: kern/kern_sysctl.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_sysctl.c,v
retrieving revision 1.50
diff -u -r1.50 kern_sysctl.c
--- kern_sysctl.c 1999/07/25 06:30:35 1.50
+++ kern_sysctl.c 1999/09/26 17:44:13
@@ -44,13 +44,14 @@
#include "opt_ddb.h"
#include "opt_insecure.h"
-#include "opt_shortcorename.h"
+#include "opt_defcorename.h"
#include "opt_sysv.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/pool.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/vnode.h>
@@ -68,6 +69,8 @@
#include <sys/mount.h>
#include <sys/syscallargs.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
#if defined(DDB)
@@ -102,9 +105,6 @@
sysctlfn *fn;
int name[CTL_MAXNAME];
- if (SCARG(uap, new) != NULL &&
- (error = suser(p->p_ucred, &p->p_acflag)))
- return (error);
/*
* all top-level sysctl names are non-terminal
*/
@@ -115,6 +115,15 @@
if (error)
return (error);
+ /*
+ * For all but CTL_PROC, must be root to change a value.
+ * For CTL_PROC, must be root, or owner of the proc (and not suid),
+ * this is checked in proc_sysctl() (once we know the targer proc).
+ */
+ if (SCARG(uap, new) != NULL && name[0] != CTL_PROC &&
+ (error = suser(p->p_ucred, &p->p_acflag)))
+ return error;
+
switch (name[0]) {
case CTL_KERN:
fn = kern_sysctl;
@@ -146,6 +155,9 @@
fn = ddb_sysctl;
break;
#endif
+ case CTL_PROC:
+ fn = proc_sysctl;
+ break;
default:
return (EOPNOTSUPP);
}
@@ -210,10 +222,12 @@
#else
int securelevel = 0;
#endif
-#ifdef SHORTCORENAME
-int shortcorename = 1;
+#ifdef DEFCORENAME
+char defcorename[MAXPATHLEN] = DEFCORENAME;
+int defcorenamelen = sizeof(DEFCORENAME);
#else
-int shortcorename = 0;
+char defcorename[MAXPATHLEN] = "%n.core";
+int defcorenamelen = sizeof("%n.core");
#endif
/*
@@ -232,7 +246,6 @@
int error, level, inthostid;
int old_autonicetime;
int old_vnodes;
- int old_shortcorename;
extern char ostype[], osrelease[], version[];
/* All sysctl names at this level, except for a few, are terminal. */
@@ -304,7 +317,7 @@
case KERN_VNODE:
return (sysctl_vnode(oldp, oldlenp, p));
case KERN_PROC:
- return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
+ return (sysctl_doeproc(name + 1, namelen - 1, oldp, oldlenp));
case KERN_FILE:
return (sysctl_file(oldp, oldlenp));
#ifdef GPROF
@@ -380,16 +393,14 @@
#else
return (sysctl_rdint(oldp, oldlenp, newp, 0));
#endif
- case KERN_SHORTCORENAME:
- /* Only allow values of zero or one. */
- old_shortcorename = shortcorename;
- error = sysctl_int(oldp, oldlenp, newp, newlen,
- &shortcorename);
- if (shortcorename != 0 && shortcorename != 1) {
- shortcorename = old_shortcorename;
- return (EINVAL);
- }
- return (error);
+ case KERN_DEFCORENAME:
+ if (newp && newlen < 1)
+ return (EINVAL);
+ error = sysctl_string(oldp, oldlenp, newp, newlen,
+ defcorename, sizeof(defcorename));
+ if (newp && !error)
+ defcorenamelen = newlen;
+ return (error);
case KERN_SYNCHRONIZED_IO:
return (sysctl_rdint(oldp, oldlenp, newp, 1));
case KERN_IOV_MAX:
@@ -498,6 +509,152 @@
}
#endif /* DEBUG */
+int
+proc_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+ struct proc *ptmp;
+ const struct proclist_desc *pd;
+ int error = 0;
+ struct rlimit alim;
+ struct plimit *newplim;
+ char *tmps = NULL;
+ int i, curlen, len;
+
+ if (namelen < 2)
+ return EINVAL;
+
+ if (name[0] == PROC_CURPROC) {
+ ptmp = p;
+ } else {
+ proclist_lock_read();
+ for (pd = proclists; pd->pd_list != NULL; pd++) {
+ for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL;
+ ptmp = LIST_NEXT(ptmp, p_list)) {
+ /* Skip embryonic processes. */
+ if (ptmp->p_stat == SIDL)
+ continue;
+ if (ptmp->p_pid == (pid_t)name[0])
+ break;
+ }
+ if (ptmp != NULL)
+ break;
+ }
+ proclist_unlock_read();
+ if (ptmp == NULL)
+ return(ESRCH);
+ if (p->p_ucred->cr_uid != 0) {
+ if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid ||
+ p->p_cred->p_ruid != ptmp->p_cred->p_svuid)
+ return EPERM;
+ if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid)
+ return EPERM; /* sgid proc */
+ for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
+ if (p->p_ucred->cr_groups[i] ==
+ ptmp->p_cred->p_rgid)
+ break;
+ }
+ if (i == p->p_ucred->cr_ngroups)
+ return EPERM;
+ }
+ }
+ if (name[1] == PROC_PID_CORENAME) {
+ if (namelen != 2)
+ return EINVAL;
+ /*
+ * Can't use sysctl_string() here because we may malloc a new
+ * area during the process, so we have to do it by hand.
+ */
+ curlen = strlen(ptmp->p_limit->pl_corename) + 1;
+ if (oldp && *oldlenp < curlen)
+ return (ENOMEM);
+ if (newp) {
+ if (securelevel > 2)
+ return EPERM;
+ if (newlen > MAXPATHLEN)
+ return ENAMETOOLONG;
+ tmps = malloc(newlen + 1, M_TEMP, M_WAITOK);
+ if (tmps == NULL)
+ return ENOMEM;
+ error = copyin(newp, tmps, newlen + 1);
+ tmps[newlen] = '\0';
+ if (error)
+ goto cleanup;
+ /* Enforce to be either 'core' for end with '.core' */
+ if (newlen < 4) { /* c.o.r.e */
+ error = EINVAL;
+ goto cleanup;
+ }
+ len = newlen - 4;
+ if (len > 0) {
+ if (tmps[len - 1] != '.' &&
+ tmps[len - 1] != '/') {
+ error = EINVAL;
+ goto cleanup;
+ }
+ }
+ if (strcmp(&tmps[len], "core") != 0) {
+ error = EINVAL;
+ goto cleanup;
+ }
+ }
+ if (oldp) {
+ *oldlenp = curlen;
+ error = copyout(ptmp->p_limit->pl_corename, oldp,
+ curlen);
+ }
+ if (newp && error == 0) {
+ /* if the 2 strings are identical, don't limcopy() */
+ if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) {
+ error = 0;
+ goto cleanup;
+ }
+ if (ptmp->p_limit->p_refcnt > 1 &&
+ (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) {
+ newplim = limcopy(ptmp->p_limit);
+ limfree(ptmp->p_limit);
+ ptmp->p_limit = newplim;
+ } else if (ptmp->p_limit->pl_corename != defcorename) {
+ free(ptmp->p_limit->pl_corename, M_TEMP);
+ }
+ ptmp->p_limit->pl_corename = tmps;
+ return (0);
+ }
+cleanup:
+ if (tmps)
+ free(tmps, M_TEMP);
+ return (error);
+ }
+ if (name[1] == PROC_PID_LIMIT) {
+ if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID)
+ return EINVAL;
+ memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim));
+ if (name[3] == PROC_PID_LIMIT_TYPE_HARD)
+ error = sysctl_quad(oldp, oldlenp, newp, newlen,
+ &alim.rlim_max);
+ else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT)
+ error = sysctl_quad(oldp, oldlenp, newp, newlen,
+ &alim.rlim_cur);
+ else
+ error = EINVAL;
+
+ if (error)
+ return error;
+
+ if (newp)
+ error = dosetrlimit(ptmp, p->p_cred,
+ name[2] - 1, &alim);
+ return error;
+ }
+ return (EINVAL);
+}
+
/*
* Validate parameters and get old / set new parameters
* for an integer-valued sysctl function.
@@ -548,6 +705,55 @@
/*
* Validate parameters and get old / set new parameters
+ * for an quad-valued sysctl function.
+ */
+int
+sysctl_quad(oldp, oldlenp, newp, newlen, valp)
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ quad_t *valp;
+{
+ int error = 0;
+
+ if (oldp && *oldlenp < sizeof(quad_t))
+ return (ENOMEM);
+ if (newp && newlen != sizeof(quad_t))
+ return (EINVAL);
+ *oldlenp = sizeof(quad_t);
+ if (oldp)
+ error = copyout(valp, oldp, sizeof(quad_t));
+ if (error == 0 && newp)
+ error = copyin(newp, valp, sizeof(quad_t));
+ return (error);
+}
+
+/*
+ * As above, but read-only.
+ */
+int
+sysctl_rdquad(oldp, oldlenp, newp, val)
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ quad_t val;
+{
+ int error = 0;
+
+ if (oldp && *oldlenp < sizeof(quad_t))
+ return (ENOMEM);
+ if (newp)
+ return (EPERM);
+ *oldlenp = sizeof(quad_t);
+ if (oldp)
+ error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
+ return (error);
+}
+
+
+/*
+ * Validate parameters and get old / set new parameters
* for a string-valued sysctl function.
*/
int
@@ -709,7 +915,7 @@
#define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc))
int
-sysctl_doproc(name, namelen, where, sizep)
+sysctl_doeproc(name, namelen, where, sizep)
int *name;
u_int namelen;
char *where;
--yrj/dFKFPuw6o+aM--