[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#308561: ssh: sftp rename fails on filesystems that don't support hard links



Package: ssh
Version: 1:3.8.1p1-8.sarge.4
Severity: normal
Tags: patch

Using sftp to access FAT32 partitions often fails. Specifically, if a
rename is requested, the operation will fail with "permission denied"
when in fact the user is allowed to rename the file. The failure is
due to sftp-server's use of link(2) to avoid races. FAT32 does not
support hard-links. sftp-server does not properly handle a failure
return from link(2) and fall back to rename(2).

The patch below is partially a backport from 3.9p1 (I think), but that
version actually checks for an incorrect error identifier. link(2)
returns EPERM in this case, not EOPNOTSUPP.

--- sftp-server.c       2004-02-23 17:19:15.000000000 -0500
+++ ../openssh-3.8.1p1-patched/sftp-server.c 2005-05-11 00:44:59.000000000 -0400
@@ -839,9 +839,29 @@
               status = errno_to_portable(errno);
       else if (S_ISREG(sb.st_mode)) {
               /* Race-free rename of regular files */
-               if (link(oldpath, newpath) == -1)
-                       status = errno_to_portable(errno);
-               else if (unlink(oldpath) == -1) {
+               if (link(oldpath, newpath) == -1) {
+                       if (errno == EPERM
+#ifdef LINK_OPNOTSUPP_ERRNO
+                           || errno == LINK_OPNOTSUPP_ERRNO
+#endif
+                           ) {
+                               struct stat st;
+
+                               /*
+                                * fs doesn't support links, so fall back to
+                                * stat+rename.  This is racy.
+                                */
+                               if (stat(newpath, &st) == -1) {
+                                       if (rename(oldpath, newpath) == -1)
+                                               status =
+ errno_to_portable(errno);
+                                       else
+                                               status = SSH2_FX_OK;
+                               }
+                       } else {
+                               status = errno_to_portable(errno);
+                       }
+               } else if (unlink(oldpath) == -1) {
                       status = errno_to_portable(errno);
                       /* clean spare link */
                       unlink(newpath);

-- System Information:
Debian Release: 3.1
 APT prefers testing
 APT policy: (700, 'testing'), (600, 'unstable')
Architecture: i386 (i686)
Kernel: Linux 2.6.11.7
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages ssh depends on:
ii  adduser                     3.63         Add and remove users and groups
ii debconf 1.4.49 Debian configuration management sy ii dpkg 1.10.27 Package maintenance system for Deb ii libc6 2.3.2.ds1-21 GNU C Library: Shared libraries an ii libpam-modules 0.76-22 Pluggable Authentication Modules f ii libpam-runtime 0.76-22 Runtime support for the PAM librar ii libpam0g 0.76-22 Pluggable Authentication Modules l
ii  libssl0.9.7                 0.9.7e-3     SSL shared libraries
ii libwrap0 7.6.dbs-8 Wietse Venema's TCP wrappers libra
ii  zlib1g                      1:1.2.2-4    compression library - runtime

-- debconf information excluded





Reply to: