summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-05-15 14:41:44 +0000
committerkib <kib@FreeBSD.org>2009-05-15 14:41:44 +0000
commitb8162aa0c9949012533f0436d057c8cc5bea571d (patch)
treea1e1849bdaee878cee7f1db0dbcc112f176a05e1 /sys
parent8a2fb32a355e541af361a07d738b6d02936d1e43 (diff)
downloadFreeBSD-src-b8162aa0c9949012533f0436d057c8cc5bea571d.zip
FreeBSD-src-b8162aa0c9949012533f0436d057c8cc5bea571d.tar.gz
Revert r192094. The revision caused problems for sysctl(3) consumers
that expect that oldlen is filled with required buffer length even when supplied buffer is too short and returned error is ENOMEM. Redo the fix for kern.proc.filedesc, by reverting the req->oldidx when remaining buffer space is too short for the current kinfo_file structure. Also, only ignore ENOMEM. We have to convert ENOMEM to no error condition to keep existing interface for the sysctl, though. Reported by: ed, Florian Smeets <flo kasimir com> Tested by: pho
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_descrip.c17
-rw-r--r--sys/kern/kern_sysctl.c8
2 files changed, 18 insertions, 7 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index f29b0eb..e0008e6 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -2883,6 +2883,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
struct proc *p;
struct tty *tp;
int vfslocked;
+ size_t oldidx;
name = (int *)arg1;
if ((p = pfind((pid_t)name[0])) == NULL)
@@ -3061,14 +3062,26 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
strlen(kif->kf_path) + 1;
kif->kf_structsize = roundup(kif->kf_structsize,
sizeof(uint64_t));
+ oldidx = req->oldidx;
error = SYSCTL_OUT(req, kif, kif->kf_structsize);
- if (error)
+ if (error) {
+ if (error == ENOMEM) {
+ /*
+ * The hack to keep the ABI of sysctl
+ * kern.proc.filedesc intact, but not
+ * to account a partially copied
+ * kinfo_file into the oldidx.
+ */
+ req->oldidx = oldidx;
+ error = 0;
+ }
break;
+ }
}
FILEDESC_SUNLOCK(fdp);
fddrop(fdp);
free(kif, M_TEMP);
- return (0);
+ return (error);
}
static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD,
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index bf539be..0a8a096 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1223,9 +1223,9 @@ sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
if (i > 0)
bcopy(p, (char *)req->oldptr + req->oldidx, i);
}
+ req->oldidx += l;
if (req->oldptr && i != l)
return (ENOMEM);
- req->oldidx += l;
return (0);
}
@@ -1322,10 +1322,9 @@ sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
size_t i, len, origidx;
origidx = req->oldidx;
- if (req->oldptr == NULL) {
- req->oldidx += l;
+ req->oldidx += l;
+ if (req->oldptr == NULL)
return (0);
- }
/*
* If we have not wired the user supplied buffer and we are currently
* holding locks, drop a witness warning, as it's possible that
@@ -1347,7 +1346,6 @@ sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
return (error);
if (i < l)
return (ENOMEM);
- req->oldidx += l;
return (0);
}
OpenPOWER on IntegriCloud