Ticket #3441: 0001-Ticket-3441-fix-Linux-kernel-specific-segfault-on-st.patch

File 0001-Ticket-3441-fix-Linux-kernel-specific-segfault-on-st.patch, 10.1 KB (added by andrew_b, 9 years ago)
  • m4.include/ls-mntd-fs.m4

    From 8fc04194435f3a07efa73f21532bdb5d6d1f8670 Mon Sep 17 00:00:00 2001
    From: Andrew Borodin <aborodin@vmail.ru>
    Date: Sat, 11 Apr 2015 12:12:50 +0300
    Subject: [PATCH] Ticket #3441: fix Linux kernel-specific segfault on startup.
    
    Sync with gnulib 3fb6e360363744462ce15c381f0b116c6fc4ce82.
    
    src/filemanager/mountlist.c: remove dependency on libmount.
    Parse /proc/self/mountinfo directly, rather than depending on libmount,
    which has many dependencies due to its dependence on libselinux, as
    detailed at:
    http://lists.gnu.org/archive/html/bug-gnulib/2015-01/msg00063.html.
    Note we restrict this to __linux__ as that's probably where this
    interface will remain.  If ever porting, it would be best to first pull
    the makedev() wrapper from coreutils to a gnulib module.
    
    Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
    ---
     m4.include/ls-mntd-fs.m4    |  23 ++------
     src/filemanager/mountlist.c | 124 ++++++++++++++++++++++++++++++++++----------
     2 files changed, 102 insertions(+), 45 deletions(-)
    
    diff --git a/m4.include/ls-mntd-fs.m4 b/m4.include/ls-mntd-fs.m4
    index c29f0aa..7e4aa19 100644
    a b  
    1 # serial 29 
     1# serial 32 
    22# How to list mounted file systems. 
    33 
    4 # Copyright (C) 1998-2004, 2006, 2009-2011 Free Software Foundation, Inc. 
     4# Copyright (C) 1998-2004, 2006, 2009-2015 Free Software Foundation, Inc. 
    55# 
    66# This file is free software; the Free Software Foundation 
    77# gives unlimited permission to copy and/or distribute it, 
    if test -z "$ac_list_mounted_fs"; then 
    110110    AC_DEFINE([MOUNTED_VMOUNT], [1], 
    111111        [Define if there is a function named mntctl that can be used to read 
    112112         the list of mounted file systems, and there is a system header file 
    113          that declares 'struct vmount.'  (AIX)]) 
     113         that declares 'struct vmount'.  (AIX)]) 
    114114  fi 
    115115fi 
    116116 
    if test $ac_cv_func_getmntent = yes; then 
    120120  # Determine whether it's the one-argument variant or the two-argument one. 
    121121 
    122122  if test -z "$ac_list_mounted_fs"; then 
    123     # 4.3BSD, SunOS, HP-UX, Dynix, Irix 
     123    # GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix 
    124124    AC_MSG_CHECKING([for one-argument getmntent function]) 
    125125    AC_CACHE_VAL([fu_cv_sys_mounted_getmntent1], 
    126126                 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 
    if test $ac_cv_func_getmntent = yes; then 
    152152         of mounted file systems, and that function takes a single argument. 
    153153         (4.3BSD, SunOS, HP-UX, Dynix, Irix)]) 
    154154      AC_CHECK_FUNCS([hasmntopt]) 
    155  
    156       # Check for libmount to support /proc/self/mountinfo on Linux 
    157       AC_CACHE_VAL([ac_cv_lib_libmount_mnt_table_parse_stream], 
    158         [AC_CHECK_LIB([mount], [mnt_new_table_from_file], 
    159           ac_cv_lib_mount_mnt_table_parse_stream=yes, 
    160           ac_cv_lib_mount_mnt_table_parse_stream=no)]) 
    161       if test $ac_cv_lib_mount_mnt_table_parse_stream = yes; then 
    162          AC_DEFINE([MOUNTED_PROC_MOUNTINFO], [1], 
    163            [Define if want to use /proc/self/mountinfo on Linux.]) 
    164          LIBS="-lmount $LIBS" 
    165       elif test -f /proc/self/mountinfo; then 
    166          AC_MSG_WARN([/proc/self/mountinfo present but libmount is missing.]) 
    167       fi 
    168155    fi 
    169156  fi 
    170157 
    if test -z "$ac_list_mounted_fs"; then 
    353340      ac_list_mounted_fs=found 
    354341      AC_DEFINE([MOUNTED_INTERIX_STATVFS], [1], 
    355342                [Define if we are on interix, and ought to use statvfs plus 
    356                  some special knowledge on where mounted filesystems can be 
     343                 some special knowledge on where mounted file systems can be 
    357344                 found. (Interix)]) 
    358345    fi 
    359346    ;; 
  • src/filemanager/mountlist.c

    diff --git a/src/filemanager/mountlist.c b/src/filemanager/mountlist.c
    index 991ebc3..1bc5b33 100644
    a b  
    8787 
    8888#ifdef MOUNTED_GETMNTENT1       /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */ 
    8989#include <mntent.h> 
     90#include <sys/types.h> 
    9091#ifndef MOUNTED 
    9192#ifdef _PATH_MOUNTED            /* GNU libc  */ 
    9293#define MOUNTED _PATH_MOUNTED 
     
    157158#include <sys/mntent.h> 
    158159#endif 
    159160 
    160 #ifdef MOUNTED_PROC_MOUNTINFO 
    161 /* Use /proc/self/mountinfo instead of /proc/self/mounts (/etc/mtab) 
    162  * on Linux, if available */ 
    163 #include <libmount/libmount.h> 
    164 #endif 
    165  
    166161#ifndef HAVE_HASMNTOPT 
    167162#define hasmntopt(mnt, opt) ((char *) 0) 
    168163#endif 
    statfs (char *file, struct statfs *fsb) 
    613608 
    614609/* --------------------------------------------------------------------------------------------- */ 
    615610 
     611#if defined MOUNTED_GETMNTENT1 && defined __linux__ 
     612 
     613/* Unescape the paths in mount tables. 
     614   STR is updated in place.  */ 
     615static void 
     616unescape_tab (char *str) 
     617{ 
     618    size_t i, j = 0; 
     619    size_t len; 
     620 
     621    len = strlen (str) + 1; 
     622 
     623    for (i = 0; i < len; i++) 
     624    { 
     625        if (str[i] == '\\' && (i + 4 < len) 
     626            && str[i + 1] >= '0' && str[i + 1] <= '3' 
     627            && str[i + 2] >= '0' && str[i + 2] <= '7' && str[i + 3] >= '0' && str[i + 3] <= '7') 
     628        { 
     629            str[j++] = (str[i + 1] - '0') * 64 + (str[i + 2] - '0') * 8 + (str[i + 3] - '0'); 
     630            i += 3; 
     631        } 
     632        else 
     633            str[j++] = str[i]; 
     634    } 
     635} 
     636#endif 
     637 
     638/* --------------------------------------------------------------------------------------------- */ 
     639 
    616640/* Return a list of the currently mounted file systems, or NULL on error. 
    617641   Add each entry to the tail of the list so that they stay in order. 
    618642   If NEED_FS_TYPE is true, ensure that the file system type fields in 
    read_file_system_list (int need_fs_type) 
    658682 
    659683#ifdef MOUNTED_GETMNTENT1       /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */ 
    660684    { 
    661 #ifdef MOUNTED_PROC_MOUNTINFO 
    662         struct libmnt_table *fstable = NULL; 
     685        FILE *fp; 
    663686 
    664         fstable = mnt_new_table_from_file ("/proc/self/mountinfo"); 
     687#ifdef __linux__ 
     688        /* Try parsing mountinfo first, as that make device IDs available. 
     689           Note we could use libmount routines to simplify this parsing a little 
     690           (and that code is in previous versions of this function), however 
     691           libmount depends on libselinux which pulls in many dependencies.  */ 
     692        char const *mountinfo = "/proc/self/mountinfo"; 
    665693 
    666         if (fstable != NULL) 
     694        fp = fopen (mountinfo, "r"); 
     695        if (fp != NULL) 
    667696        { 
    668             struct libmnt_fs *fs; 
    669             struct libmnt_iter *iter; 
     697            char *line = NULL; 
     698            size_t buf_size = 0; 
    670699 
    671             iter = mnt_new_iter (MNT_ITER_FORWARD); 
    672  
    673             while (iter && mnt_table_next_fs (fstable, iter, &fs) == 0) 
     700            while (getline (&line, &buf_size, fp) != -1) 
    674701            { 
     702                unsigned int devmaj, devmin; 
     703                int target_s, target_e, type_s, type_e, source_s, source_e; 
     704                char test; 
     705                char *dash; 
     706                int rc; 
     707 
     708                rc = sscanf (line, "%*u "       /* id - discarded  */ 
     709                             "%*u "     /* parent - discarded */ 
     710                             "%u:%u "   /* dev major:minor  */ 
     711                             "%*s "     /* mountroot - discarded  */ 
     712                             "%n%*s%n"  /* target, start and end  */ 
     713                             "%c",      /* more data...  */ 
     714                             &devmaj, &devmin, &target_s, &target_e, &test); 
     715                if (rc != 3 && rc != 5) /* 5 if %n included in count.  */ 
     716                    continue; 
     717 
     718                /* skip optional fields, terminated by " - "  */ 
     719                dash = strstr (line + target_e, " - "); 
     720                if (dash == NULL) 
     721                    continue; 
     722 
     723                rc = sscanf (dash, " - "        /* */ 
     724                             "%n%*s%n " /* FS type, start and end  */ 
     725                             "%n%*s%n " /* source, start and end  */ 
     726                             "%c",      /* more data...  */ 
     727                             &type_s, &type_e, &source_s, &source_e, &test); 
     728                if (rc != 1 && rc != 5) /* 5 if %n included in count.  */ 
     729                    continue; 
     730 
     731                /* manipulate the sub-strings in place.  */ 
     732                line[target_e] = '\0'; 
     733                dash[type_e] = '\0'; 
     734                dash[source_e] = '\0'; 
     735                unescape_tab (dash + source_s); 
     736                unescape_tab (line + target_s); 
     737 
    675738                me = g_malloc (sizeof *me); 
    676739 
    677                 me->me_devname = g_strdup (mnt_fs_get_source (fs)); 
    678                 me->me_mountdir = g_strdup (mnt_fs_get_target (fs)); 
    679                 me->me_type = g_strdup (mnt_fs_get_fstype (fs)); 
     740                me->me_devname = strdup (dash + source_s); 
     741                me->me_mountdir = strdup (line + target_s); 
     742                me->me_type = strdup (dash + type_s); 
    680743                me->me_type_malloced = 1; 
    681                 me->me_dev = mnt_fs_get_devno (fs); 
    682                 /* Note we don't use mnt_fs_is_pseudofs() or mnt_fs_is_netfs() here 
    683                    as libmount's classification is non-compatible currently. 
    684                    Also we pass "false" for the "Bind" option as that's only 
     744                me->me_dev = makedev (devmaj, devmin); 
     745                /* we pass "false" for the "Bind" option as that's only 
    685746                   significant when the Fs_type is "none" which will not be 
    686747                   the case when parsing "/proc/self/mountinfo", and only 
    687748                   applies for static /etc/mtab files.  */ 
    read_file_system_list (int need_fs_type) 
    693754                mtail = &me->me_next; 
    694755            } 
    695756 
    696             mnt_free_iter (iter); 
    697             mnt_free_table (fstable); 
     757            free (line); 
     758 
     759            if (ferror (fp) != 0) 
     760            { 
     761                int saved_errno = errno; 
     762 
     763                fclose (fp); 
     764                errno = saved_errno; 
     765                goto free_then_fail; 
     766            } 
    698767 
     768            if (fclose (fp) == EOF) 
     769                goto free_then_fail; 
    699770        } 
    700         else                    /* fallback to /proc/self/mounts (/etc/mtab) if anything failed */ 
    701 #endif /* MOUNTED_PROC_MOUNTINFO */ 
     771        else                    /* fallback to /proc/self/mounts (/etc/mtab). */ 
     772#endif /* __linux __ */ 
    702773        { 
    703             FILE *fp; 
    704774            struct mntent *mnt; 
    705775            const char *table = MOUNTED; 
    706776