]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - sysfs.c
sysfs: avoid possible data corruption in sys_load.
[thirdparty/mdadm.git] / sysfs.c
diff --git a/sysfs.c b/sysfs.c
index a28442137c3399cdd3146882c3f3db158698c4d3..8979ec4e23c80fd1812fe6b4f277cc4ad325d923 100644 (file)
--- a/sysfs.c
+++ b/sysfs.c
@@ -37,7 +37,7 @@ int load_sys(char *path, char *buf)
        if (n <0 || n >= 1024)
                return -1;
        buf[n] = 0;
-       if (buf[n-1] == '\n')
+       if (n && buf[n-1] == '\n')
                buf[n-1] = 0;
        return 0;
 }
@@ -59,15 +59,9 @@ void sysfs_free(struct mdinfo *sra)
 int sysfs_open(int devnum, char *devname, char *attr)
 {
        char fname[50];
-       char sys_name[16];
        int fd;
-       if (devnum >= 0)
-               sprintf(sys_name, "md%d", devnum);
-       else
-               sprintf(sys_name, "md_d%d",
-                       -1-devnum);
 
-       sprintf(fname, "/sys/block/%s/md/", sys_name);
+       sprintf(fname, "/sys/block/%s/md/", devnum2devname(devnum));
        if (devname) {
                strcat(fname, devname);
                strcat(fname, "/");
@@ -234,7 +228,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                        strcpy(dbase, "size");
                        if (load_sys(fname, buf))
                                goto abort;
-                       dev->component_size = strtoull(buf, NULL, 0);
+                       dev->component_size = strtoull(buf, NULL, 0) * 2;
                }
                if (options & GET_STATE) {
                        dev->disk.state = 0;
@@ -359,7 +353,7 @@ int sysfs_set_array(struct mdinfo *sra,
        rv |= sysfs_set_num(sra, NULL, "raid_disks", info->array.raid_disks);
        rv |= sysfs_set_num(sra, NULL, "chunk_size", info->array.chunk_size);
        rv |= sysfs_set_num(sra, NULL, "layout", info->array.layout);
-       rv |= sysfs_set_num(sra, NULL, "component_size", info->component_size);
+       rv |= sysfs_set_num(sra, NULL, "component_size", info->component_size/2);
        rv |= sysfs_set_num(sra, NULL, "resync_start", info->resync_start);
        sra->array = info->array;
        return rv;
@@ -380,14 +374,16 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd)
 
        memset(nm, 0, sizeof(nm));
        sprintf(dv, "/sys/dev/block/%d:%d", sd->disk.major, sd->disk.minor);
-       if (readlink(dv, nm, sizeof(nm)) < 0)
+       rv = readlink(dv, nm, sizeof(nm));
+       if (rv <= 0)
                return -1;
+       nm[rv] = '\0';
        dname = strrchr(nm, '/');
        if (dname) dname++;
        strcpy(sd->sys_name, "dev-");
        strcpy(sd->sys_name+4, dname);
 
-       rv |= sysfs_set_num(sra, sd, "offset", sd->data_offset);
+       rv = sysfs_set_num(sra, sd, "offset", sd->data_offset);
        rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2);
        if (sra->array.level != LEVEL_CONTAINER) {
                rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk);