From okor@ns.salut.ru  Wed Oct 13 17:38:58 2004
Return-Path: <okor@ns.salut.ru>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP
	id 7844116A4CE; Wed, 13 Oct 2004 17:38:58 +0000 (GMT)
Received: from ns.salut.ru (ns.salut.ru [194.67.150.71])
	by mx1.FreeBSD.org (Postfix) with ESMTP
	id A735543D41; Wed, 13 Oct 2004 17:38:57 +0000 (GMT)
	(envelope-from okor@ns.salut.ru)
Received: from ns.salut.ru (ns.salut.ru [194.67.150.71] (may be forged))
	by ns.salut.ru (8.12.11/8.12.11) with ESMTP id i9DHcuNs090237;
	Wed, 13 Oct 2004 21:38:56 +0400 (MSD)
	(envelope-from okor@ns.salut.ru)
Received: (from okor@localhost)
	by ns.salut.ru (8.12.11/8.12.11/Submit) id i9DHctAx090236;
	Wed, 13 Oct 2004 21:38:55 +0400 (MSD)
	(envelope-from okor)
Message-Id: <200410131738.i9DHctAx090236@ns.salut.ru>
Date: Wed, 13 Oct 2004 21:38:55 +0400 (MSD)
From: Oleg Koreshkov <okor@NONEXISTENT.zone.salut.ru>
Reply-To: Oleg Koreshkov <okor@NONEXISTENT.zone.salut.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc: yar@freebsd.org
Subject: ftpd process can hang with high cpu load   
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         72649
>Category:       bin
>Synopsis:       ftpd process can hang with high cpu load
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    yar
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 13 17:40:24 GMT 2004
>Closed-Date:    Mon Nov 15 11:15:20 GMT 2004
>Last-Modified:  Mon Nov 15 11:15:20 GMT 2004
>Originator:     Oleg Koreshkov (okor (AT) zone.salut.ru)
>Release:        FreeBSD 4.10-RELEASE-p2 i386 (CURRENT has the same bug)
>Organization:
none
>Environment:
FreeBSD 4.10
>Description:
        ftpd process can consume 100% CPU doing nothing, looping endless loop,
        if transferd file was overwritten during transfer.
        If client of this session hangs, this ftpd process can live quite a
        long time (2 hours or even more).
>How-To-Repeat:
        Start transfer (TYPE I) of big file or delay transfer by ipfw pipe.
        In another ftp session overwrite this file with smaller size (size must be > 0).
        First ftpd process gets in to endless loop.
>Fix:
--- ftpd.c
+++ ftpd.c
@@ -2034,6 +2034,22 @@
 
 					goto data_err;
 				}
+
+				/*
+				 * sendfile(2) can return zero bytes written
+				 * (cnt == 0), without indicating error,
+				 * when file was truncated (by another process)
+				 * during transfer.
+				 * We consider this case as temporary error,
+				 * however it possible to treat it
+				 * as successful transfer completion.
+				 */
+				if (cnt == 0) {
+					transflag = 0;
+					reply(450, "File was overwritten "
+					    "during transfer.");
+					return (-1);
+				}
 			}
 
 			transflag = 0;
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->yar 
Responsible-Changed-By: yar 
Responsible-Changed-When: Thu Oct 14 09:24:18 GMT 2004 
Responsible-Changed-Why:  
I'll try to deal with this bug. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=72649 

From: Yar Tikhiy <yar@FreeBSD.org>
To: okor@zone.salut.ru
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/72649: ftpd process can hang with high cpu load
Date: Thu, 14 Oct 2004 16:11:57 +0400

 I see the problem, but I cannot see why you decided ftpd should
 report a temporary error.  On the one hand, if the file has been
 truncated, you'll be unlikely to get its original contents upon a
 retry, so it should be a permanent error if at all.  On the other
 hand, if someone truncates the file you're read(2)'ing, you'll get
 just an EOF indication you cannot tell from the real EOF.  Therefore
 I'd vote for returning no error in the case of sendfile(2) either.
 A malicious or careless party having access to the file you're
 getting via any method, even local cp(1), can mangle it in many
 other ways, and there are means to detect all of them, like strong
 cryptography or, in a more relaxed environment, file checksums.
 
 By the way, the sendfile(2) manpage doesn't seem to mention this
 case.  I think it should be extended a little with relevant details.
 Sendfile(2) will return no error (0) and set *sbytes to 0 in any
 case when it hits the EOF before sending out any data, won't it?
 
 -- 
 Yar

From: Yar Tikhiy <yar@freebsd.org>
To: okor@zone.salut.ru
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: bin/72649: ftpd process can hang with high cpu load
Date: Thu, 14 Oct 2004 17:32:51 +0400

 On Thu, Oct 14, 2004 at 04:57:05PM +0400, okor@NONEXISTENT.zone.salut.ru wrote:
 > >I see the problem, but I cannot see why you decided ftpd should
 > >report a temporary error.  On the one hand, if the file has been
 > >truncated, you'll be unlikely to get its original contents upon a
 > >retry, so it should be a permanent error if at all.  On the other
 > >hand, if someone truncates the file you're read(2)'ing, you'll get
 > >just an EOF indication you cannot tell from the real EOF.  Therefore
 > >I'd vote for returning no error in the case of sendfile(2) either.
 > >A malicious or careless party having access to the file you're
 > >getting via any method, even local cp(1), can mangle it in many
 > >other ways, and there are means to detect all of them, like strong
 > >cryptography or, in a more relaxed environment, file checksums.
 > 
 > Yes I agree with you... I'd even say I've made patch this way 
 > (returning eror) mainly to show when error triggers.
 
 All right, I'll implement the no-error approach to handling the case.
 
 > >By the way, the sendfile(2) manpage doesn't seem to mention this
 > >case.  I think it should be extended a little with relevant details.
 > >Sendfile(2) will return no error (0) and set *sbytes to 0 in any
 > >case when it hits the EOF before sending out any data, won't it?
 > 
 > Yes, it will be desirable to correct sendfile(2) manpage.
 > I was wondered when see sendfile(2) returning zero bytes without
 > indicating error. May be returning -1 and setting errno to EINVAL
 > is more correct behaviour? Though I'm not sure...
 > As example: write(2) doesn't return 0, do it?
 
 I feel that sendfile(2) is closer to pread(2) than to write(2) with
 respect to the EOF issue since it reads a plain seekable file and
 writes to a socket, which doesn't essentially have the notion of
 EOF for write/send operations (you'll sooner get SIGPIPE or EPIPE...)
 And pread(2), as well as read(2), returns 0 upon hitting the EOF.
 Note that the pread(2) manpage tells that pread(2) will indicate
 EINVAL if the offset is invalid.  The manpage means really invalid
 offsets, like negative ones, while just pread'ing beyond the EOF
 results in no error and 0 bytes read.  That's another point for me
 to correct...
 
 -- 
 Yar
State-Changed-From-To: open->patched 
State-Changed-By: yar 
State-Changed-When: Sat Oct 16 09:54:14 GMT 2004 
State-Changed-Why:  
CURRENT's ftpd has been fixed and the manpages updated. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=72649 
State-Changed-From-To: patched->closed 
State-Changed-By: yar 
State-Changed-When: Mon Nov 15 11:14:20 GMT 2004 
State-Changed-Why:  
The fix has been merged to 5-STABLE and 4-STABLE. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=72649 
>Unformatted:
         
