CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2009-09-25 18:08:04 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Handle any path supplied to dm_task_set_name() by looking up in /dev/mapper. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.300&r2=1.301 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.81&r2=1.82 --- LVM2/WHATS_NEW_DM 2009/09/15 13:54:29 1.300 +++ LVM2/WHATS_NEW_DM 2009/09/25 18:08:04 1.301 @@ -1,5 +1,6 @@ Version 1.02.38 - ===================================== + Handle any path supplied to dm_task_set_name() by looking up in /dev/mapper. Version 1.02.37 - 15th September 2009 ===================================== --- LVM2/libdm/libdm-common.c 2009/09/15 11:41:39 1.81 +++ LVM2/libdm/libdm-common.c 2009/09/25 18:08:04 1.82 @@ -23,6 +23,7 @@ #include <sys/param.h> #include <sys/ioctl.h> #include <fcntl.h> +#include <dirent.h> #ifdef UDEV_SYNC_SUPPORT # include <sys/types.h> @@ -183,9 +184,54 @@ return dmt; } +/* + * Find the name associated with a given device number by scanning _dm_dir. + */ +static char *_translate_name(dev_t st_rdev, const char *devname) +{ + const char *name; + char path[PATH_MAX]; + struct dirent *dirent; + DIR *d; + struct stat buf; + char *new_name = NULL; + + if (!(d = opendir(_dm_dir))) { + log_sys_error("opendir", _dm_dir); + return NULL; + } + + while ((dirent = readdir(d))) { + name = dirent->d_name; + + if (!strcmp(name, ".") || !strcmp(name, "..")) + continue; + + if (dm_snprintf(path, sizeof(path), "%s/%s", _dm_dir, + name) == -1) { + log_error("Couldn't create path for %s", name); + continue; + } + + if (stat(path, &buf)) + continue; + + if (buf.st_rdev == st_rdev) { + new_name = dm_strdup(name); + break; + } + } + + if (closedir(d)) + log_sys_error("closedir", _dm_dir); + + return new_name; +} + int dm_task_set_name(struct dm_task *dmt, const char *name) { char *pos; + char *new_name = NULL; char path[PATH_MAX]; struct stat st1, st2; @@ -194,8 +240,8 @@ dmt->dev_name = NULL; } - /* If path was supplied, remove it if it points to the same device - * as its last component. + /* + * Path supplied for existing device? */ if ((pos = strrchr(name, '/'))) { if (dmt->type == DM_DEVICE_CREATE) { @@ -203,23 +249,38 @@ return 0; } + if (stat(name, &st1)) { + log_error("Device %s not found", name); + return 0; + } + + /* + * If supplied path points to same device as last component + * under /dev/mapper, use that name directly. Otherwise call + * _translate_name() to scan _dm_dir for a match. + */ snprintf(path, sizeof(path), "%s/%s", _dm_dir, pos + 1); - if (stat(name, &st1) || stat(path, &st2) || - !(st1.st_dev == st2.st_dev)) { + if (!stat(path, &st2) && (st1.st_rdev == st2.st_rdev)) + name = pos + 1; + else if ((new_name = _translate_name(st1.st_rdev, pos + 1))) + name = new_name; + else { log_error("Device %s not found", name); return 0; } - - name = pos + 1; } if (strlen(name) >= DM_NAME_LEN) { log_error("Name \"%s\" too long", name); + if (new_name) + dm_free(new_name); return 0; } - if (!(dmt->dev_name = dm_strdup(name))) { + if (new_name) + dmt->dev_name = new_name; + else if (!(dmt->dev_name = dm_strdup(name))) { log_error("dm_task_set_name: strdup(%s) failed", name); return 0; }
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2010-05-27 15:02:57 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Use expected union semun for arguments in selected semaphore operations. This is standard and expected use. It also prevents errors related with misalignment of the arguments for semaphore operations on some architectures. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.373&r2=1.374 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.95&r2=1.96 --- LVM2/WHATS_NEW_DM 2010/05/20 23:21:53 1.373 +++ LVM2/WHATS_NEW_DM 2010/05/27 15:02:56 1.374 @@ -1,5 +1,6 @@ Version 1.02.49 - ================================ + Use expected union semun for arguments in selected semaphore operations. Version 1.02.48 - 17th May 2010 ================================ --- LVM2/libdm/libdm-common.c 2010/05/03 21:06:53 1.95 +++ LVM2/libdm/libdm-common.c 2010/05/27 15:02:56 1.96 @@ -43,6 +43,18 @@ #define DEV_DIR "/dev/" +#ifdef UDEV_SYNC_SUPPORT +#ifdef _SEM_SEMUN_UNDEFINED +union semun +{ + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + unsigned short int *array; /* array for GETALL & SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif +#endif + static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR; static int _verbose = 0; @@ -1076,6 +1088,7 @@ int gen_semid; uint16_t base_cookie; uint32_t gen_cookie; + union semun sem_arg; if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { log_error("Failed to open /dev/urandom " @@ -1123,7 +1136,9 @@ log_debug("Udev cookie 0x%" PRIx32 " (semid %d) created", gen_cookie, gen_semid); - if (semctl(gen_semid, 0, SETVAL, 1) < 0) { + sem_arg.val = 1; + + if (semctl(gen_semid, 0, SETVAL, sem_arg) < 0) { log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno)); /* We have to destroy just created semaphore * so it won't stay in the system. */
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2010-08-03 07:56:04 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Add check for kernel semaphore support and disable udev_sync if not available. udev_sync feature requires semaphores (part of System V IPC) to be configured in kernel (CONFIG_SYSVIPC). Check whether it is supported and if not, give a warning message and disable udev synchronisation code automatically to avoid any further error states and associated problems. One should use the kernel with System V IPC support enabled or libdevmapper with udev_sync feature disabled. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.400&r2=1.401 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.97&r2=1.98 --- LVM2/WHATS_NEW_DM 2010/07/28 21:58:08 1.400 +++ LVM2/WHATS_NEW_DM 2010/08/03 07:56:03 1.401 @@ -1,5 +1,6 @@ Version 1.02.54 - ================================ + Add check for kernel semaphore support and disable udev_sync if not available. Version 1.02.53 - 28th July 2010 ================================ --- LVM2/libdm/libdm-common.c 2010/07/09 15:34:47 1.97 +++ LVM2/libdm/libdm-common.c 2010/08/03 07:56:03 1.98 @@ -60,6 +60,7 @@ static int _verbose = 0; #ifdef UDEV_SYNC_SUPPORT +static int _semaphore_supported = -1; static int _udev_running = -1; static int _sync_with_udev = 1; static int _udev_checking = 1; @@ -929,6 +930,23 @@ #else /* UDEV_SYNC_SUPPORT */ +static int _check_semaphore_is_supported() +{ + int maxid; + union semun arg; + struct seminfo seminfo; + + arg.__buf = &seminfo; + maxid = semctl(0, 0, SEM_INFO, arg); + + if (maxid < 0) { + log_warn("Kernel not configured for semaphores (System V IPC). " + "Not using udev synchronisation code."); + return 0; + } + + return 1; +} static int _check_udev_is_running(void) { @@ -958,20 +976,27 @@ return 0; } -void dm_udev_set_sync_support(int sync_with_udev) +static void _check_udev_sync_requirements_once() { + if (_semaphore_supported < 0) + _semaphore_supported = _check_semaphore_is_supported(); + if (_udev_running < 0) _udev_running = _check_udev_is_running(); +} +void dm_udev_set_sync_support(int sync_with_udev) +{ + _check_udev_sync_requirements_once(); _sync_with_udev = sync_with_udev; } int dm_udev_get_sync_support(void) { - if (_udev_running < 0) - _udev_running = _check_udev_is_running(); + _check_udev_sync_requirements_once(); - return dm_cookie_supported() && _udev_running && _sync_with_udev; + return _semaphore_supported && dm_cookie_supported() && + _udev_running && _sync_with_udev; } void dm_udev_set_checking(int checking)
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-03-30 12:14:37 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Fix 2 signess warnings reported by gcc Replace int with unsigned counter. Replace snprintf with dm_snprintf. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.459&r2=1.460 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.115&r2=1.116 --- LVM2/WHATS_NEW_DM 2011/03/29 21:49:18 1.459 +++ LVM2/WHATS_NEW_DM 2011/03/30 12:14:36 1.460 @@ -1,5 +1,7 @@ Version 1.02.64 - =================================== + Use dm_snprintf() to fix signess warning in dm_set_dev_dir(). + Use unsigned loop counter to fix signess warning in _other_node_ops(). Fix const cast in dmsetup calls of dm_report_field_string(). Streamline /dev/mapper/control node code for common cases. Use hard-coded dm control node device number for 2.6.36 kernels and above. --- LVM2/libdm/libdm-common.c 2011/03/29 21:53:47 1.115 +++ LVM2/libdm/libdm-common.c 2011/03/30 12:14:36 1.116 @@ -794,7 +794,7 @@ /* Check if there is other the type of node operation stacked */ static int _other_node_ops(node_op_t type) { - int i; + unsigned i; for (i = 0; i < NUM_NODES; i++) if (type != i && _count_node_ops[i]) @@ -958,8 +958,7 @@ len = strlen(dev_dir); slash = dev_dir[len-1] == '/' ? "" : "/"; - if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) - >= sizeof _dm_dir) { + if (dm_snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) < 0) { log_debug("Invalid dev_dir value, %s: name too long.", dev_dir); return 0; }
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2012-02-08 11:07:17 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Fix fd resource leak in error path Use 'goto bad' to cleanup fd on error path. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.539&r2=1.540 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.135&r2=1.136 --- LVM2/WHATS_NEW_DM 2012/02/08 11:05:04 1.539 +++ LVM2/WHATS_NEW_DM 2012/02/08 11:07:17 1.540 @@ -1,5 +1,6 @@ Version 1.02.70 - =================================== + Fix fd resource leak in error path for _udev_notify_sem_create(). Leave space for '\0' for readline() call in _sysfs_get_kernel_name(). Version 1.02.69 - 1st February 2012 --- LVM2/libdm/libdm-common.c 2012/02/08 11:05:05 1.135 +++ LVM2/libdm/libdm-common.c 2012/02/08 11:07:17 1.136 @@ -1738,7 +1738,7 @@ log_error("semid %d: sem_ctl GETVAL failed for " "cookie 0x%" PRIx32 ": %s", gen_semid, gen_cookie, strerror(errno)); - return 0; + goto bad; } log_debug("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2012-02-13 10:49:28 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Do not write to -1 buffer address In case of zero bytes would be read from sysfs, it would store '\0' on temp_buf[-1] address. Simplify some buffer length calculation and use strcpy if we've just checked string fits in give buffer. Replace jump label error: with bad: commonly used in libdm. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.551&r2=1.552 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.136&r2=1.137 --- LVM2/WHATS_NEW_DM 2012/02/13 00:23:21 1.551 +++ LVM2/WHATS_NEW_DM 2012/02/13 10:49:28 1.552 @@ -1,5 +1,6 @@ Version 1.02.71 - ==================================== + Fix potential risk of writing in front of buffer in _sysfs_get_dm_name(). Version 1.02.70 - 12th February 2012 ==================================== --- LVM2/libdm/libdm-common.c 2012/02/08 11:07:17 1.136 +++ LVM2/libdm/libdm-common.c 2012/02/13 10:49:28 1.137 @@ -1191,19 +1191,18 @@ char *sysfs_path, *temp_buf; FILE *fp = NULL; int r = 0; + size_t len; if (!(sysfs_path = dm_malloc(PATH_MAX)) || !(temp_buf = dm_malloc(PATH_MAX))) { log_error("_sysfs_get_dm_name: failed to allocate temporary buffers"); - if (sysfs_path) - dm_free(sysfs_path); - return 0; + goto bad; } if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32 "/dm/name", _sysfs_dir, major, minor) < 0) { log_error("_sysfs_get_dm_name: dm_snprintf failed"); - goto error; + goto bad; } if (!(fp = fopen(sysfs_path, "r"))) { @@ -1211,23 +1210,25 @@ log_sys_error("fopen", sysfs_path); else log_sys_debug("fopen", sysfs_path); - goto error; + goto bad; } if (!fgets(temp_buf, PATH_MAX, fp)) { log_sys_error("fgets", sysfs_path); - goto error; + goto bad; } - temp_buf[strlen(temp_buf) - 1] = '\0'; - if (buf_size < strlen(temp_buf) + 1) { + len = strlen(temp_buf); + + if (len > buf_size) { log_error("_sysfs_get_dm_name: supplied buffer too small"); - goto error; + goto bad; } - strncpy(buf, temp_buf, buf_size); + temp_buf[len ? len - 1 : 0] = '\0'; /* \n */ + strcpy(buf, temp_buf); r = 1; -error: +bad: if (fp && fclose(fp)) log_sys_error("fclose", sysfs_path); @@ -1241,19 +1242,19 @@ { char *sysfs_path, *temp_buf, *name; ssize_t size; + size_t len; + int r = 0; if (!(sysfs_path = dm_malloc(PATH_MAX)) || !(temp_buf = dm_malloc(PATH_MAX))) { log_error("_sysfs_get_kernel_name: failed to allocate temporary buffers"); - if (sysfs_path) - dm_free(sysfs_path); - return 0; + goto bad; } if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32, _sysfs_dir, major, minor) < 0) { log_error("_sysfs_get_kernel_name: dm_snprintf failed"); - goto error; + goto bad; } if ((size = readlink(sysfs_path, temp_buf, PATH_MAX - 1)) < 0) { @@ -1261,30 +1262,29 @@ log_sys_error("readlink", sysfs_path); else log_sys_debug("readlink", sysfs_path); - goto error; + goto bad; } temp_buf[size] = '\0'; if (!(name = strrchr(temp_buf, '/'))) { log_error("Could not locate device kernel name in sysfs path %s", temp_buf); - goto error; + goto bad; } name += 1; + len = size - (name - temp_buf) + 1; - if (buf_size < strlen(name) + 1) { + if (len > buf_size) { log_error("_sysfs_get_kernel_name: output buffer too small"); - goto error; + goto bad; } - strncpy(buf, name, buf_size); + strcpy(buf, name); + r = 1; +bad: dm_free(sysfs_path); dm_free(temp_buf); - return 1; -error: - dm_free(sysfs_path); - dm_free(temp_buf); - return 0; + return r; } int dm_device_get_name(uint32_t major, uint32_t minor, int prefer_kernel_name,
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2012-02-28 08:36:51 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Fix dm_task_set_name to properly resolve path to dm name. Wrong variable was checked in _dm_task_set_name_from_path. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.574&r2=1.575 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.141&r2=1.142 --- LVM2/WHATS_NEW_DM 2012/02/23 22:45:43 1.574 +++ LVM2/WHATS_NEW_DM 2012/02/28 08:36:51 1.575 @@ -1,5 +1,6 @@ Version 1.02.73 - ==================================== + Fix dm_task_set_name to properly resolve path to dm name (1.02.71). Add dm_strncpy() function as a faster strncpy() replacement. Version 1.02.72 - 23rd February 2012 --- LVM2/libdm/libdm-common.c 2012/02/15 12:23:16 1.141 +++ LVM2/libdm/libdm-common.c 2012/02/28 08:36:51 1.142 @@ -526,7 +526,7 @@ return 0; } - if (!stat(path, &st2) && (st1.st_rdev == st2.st_rdev)) + if (!stat(buf, &st2) && (st1.st_rdev == st2.st_rdev)) final_name = name; else if (_find_dm_name_of_device(st1.st_rdev, buf, sizeof(buf))) final_name = buf;
CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2012-03-05 12:45:43 Modified files: . : WHATS_NEW_DM libdm : libdm-common.c Log message: Fix dm_task_get_name_unmangled to not unmangle already unmangled name. In 'auto' and 'hex' mode, these names are already unmangled on ioctl return. There's no point on trying to do that once again (actually it's a bug!). Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.587&r2=1.588 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-common.c.diff?cvsroot=lvm2&r1=1.145&r2=1.146 --- LVM2/WHATS_NEW_DM 2012/03/05 12:43:03 1.587 +++ LVM2/WHATS_NEW_DM 2012/03/05 12:45:43 1.588 @@ -1,5 +1,6 @@ Version 1.02.74 - ================================ + Fix dm_task_get_name_unmangled to not unmangle already unmangled name. Check whether device names are properly mangled on ioctl return. Deactivation of failed thin check on thin pool returns success. --- LVM2/libdm/libdm-common.c 2012/03/05 12:43:03 1.145 +++ LVM2/libdm/libdm-common.c 2012/03/05 12:45:43 1.146 @@ -588,9 +588,14 @@ const char *s = dm_task_get_name(dmt); char buf[DM_NAME_LEN]; char *rs = NULL; - int r; + int r = 0; - if ((r = unmangle_name(s, strlen(s), buf, sizeof(buf), + /* + * Unless the mode used is 'none', the name + * is *already* unmangled on ioctl return! + */ + if (dm_get_name_mangling_mode() == DM_STRING_MANGLING_NONE && + (r = unmangle_name(s, strlen(s), buf, sizeof(buf), dm_get_name_mangling_mode())) < 0) log_error("Failed to unmangle device name \"%s\".", s); else if (!(rs = r ? dm_strdup(buf) : dm_strdup(s)))