bin/143570: [patch] stock ftpd does not handle "filesize" limit right

Eugene Grosbein egrosbein at rdtc.ru
Fri Feb 5 06:40:02 UTC 2010


>Number:         143570
>Category:       bin
>Synopsis:       [patch] stock ftpd does not handle "filesize" limit right
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Feb 05 06:40:01 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 6.4-STABLE i386
>Organization:
RDTC JSC
>Environment:
System: FreeBSD hq.delikates-nk.ru 6.4-STABLE FreeBSD 6.4-STABLE #8: Mon Feb 1 22:28:06 KRAT 2010 root at hq.delikates-nk.ru:/usr/local/obj/usr/local/src/sys/HQ i386

>Description:
	There are some problems with stock ftpd concerning
	"filesize" limit processing.

	1. ftpd calls setusercontext() for authenticated user
	with LOGIN_SETRESOURCES flag too early, before it updates wtmp.
	It wtmp is large enough and user has filesize limit low,
	ftpd's write to wtmp fails.

	2. ftpd may not revert to superuser's context at the end
	of user session and therefore fail to note session end in wtmp
	(see above).

	3. If ftpd hits limit while writing to disk file at user's request
	it is instantly killed with SIGXFSZ. Instead, it should process it
	gracefully, report an error to the user and contiue with the session.

>How-To-Repeat:

	Add new login class with "filesize=NNN" to /etc/login.conf
	(don't forget to run cap_mkdb /etc/login.conf after).
	assign this class to a user and try to login to ftp server
	as this user:

	- if your wtmp file size is greater than NNN, you'll be instantly
	disconnected;
	- otherwise, try to upload a file bigger than NNN in size,
	your connection will break after uploading NNN bytes.

>Fix:

--- libexec/ftpd/ftpd.c.orig	2010-02-05 11:19:23.000000000 +0700
+++ libexec/ftpd/ftpd.c	2010-02-05 13:02:10.000000000 +0700
@@ -428,6 +428,10 @@
 		}
 	}
 
+	/* handge filesize limit gracefully */
+	sa.sa_handler = SIG_IGN;
+	(void)sigaction(SIGXFSZ, &sa, NULL);
+
 	if (daemon_mode) {
 		int *ctl_sock, fd, maxfd = -1, nfds, i;
 		fd_set defreadfds, readfds;
@@ -1183,14 +1187,16 @@
 #endif
 
 	(void) seteuid(0);
-	if (logged_in && dowtmp)
-		ftpd_logwtmp(ttyline, "", NULL);
-	pw = NULL;
 #ifdef	LOGIN_CAP
 	setusercontext(NULL, getpwuid(0), 0,
 		       LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK|
 		       LOGIN_SETMAC);
 #endif
+
+	if (logged_in && dowtmp)
+		ftpd_logwtmp(ttyline, "", NULL);
+	pw = NULL;
+
 #ifdef USE_PAM
 	if (pamh) {
 		if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
@@ -1463,7 +1469,7 @@
 	}
 	setusercontext(lc, pw, 0,
 		LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
-		LOGIN_SETRESOURCES|LOGIN_SETUMASK|LOGIN_SETMAC);
+		LOGIN_SETUMASK|LOGIN_SETMAC);
 #else
 	setlogin(pw->pw_name);
 	(void) initgroups(pw->pw_name, pw->pw_gid);
@@ -1485,6 +1491,10 @@
 		    (struct sockaddr *)&his_addr);
 	logged_in = 1;
 
+#ifdef	LOGIN_CAP
+	setusercontext(lc, pw, 0,LOGIN_SETRESOURCES);
+#endif
+
 	if (guest && stats && statfd < 0)
 #ifdef VIRTUAL_HOSTING
 		statfd = open(thishost->statfile, O_WRONLY|O_APPEND);
@@ -2743,6 +2753,13 @@
 dologout(int status)
 {
 
+	(void) seteuid(0);
+#ifdef	LOGIN_CAP
+	setusercontext(NULL, getpwuid(0), 0,
+		       LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK|
+		       LOGIN_SETMAC);
+#endif
+
 	if (logged_in && dowtmp) {
 		(void) seteuid(0);
 		ftpd_logwtmp(ttyline, "", NULL);
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list