From cd294a12553a0f24096c98c2dc59f4b0ec4a5c14 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Wed, 19 Dec 2018 17:48:54 -0700 Subject: [PATCH] LU-11809 llite: don't use %p to generate cfg_instance In kernel 4.15 and later, using "%p" in a string format to print a kernel pointer will result in the pointer being hashed with a random value, and the high bytes will be masked on 64-bit CPUs to prevent leaking kernel address-space info to userspace to defeat ASLR. In early boot, the "%p" pointer may resolve to " (ptrval)", if there is not enough entropy in the system to generate a random hash value. The superblock pointer is used on the client to uniquely identify all of the OBD devices connected to it, and to find the configuration llog that was used to mount the filesystem, so that it can also be used at unmount time. The sb pointer is also used in the OBD device names, and the " (ptrval)" expansion breaks /sys filenames, and also breaks the uniqueness of the config instance. On the server, there is also a pointer value used for the FLDB SEQ servers of the OSTs. For the short term, bypass the "%p" hashing, so that mount continues to work properly, and this can be resolved in a later patch to change ll_get_cfg_instance() to provide a unique value that is not directly a kernel pointer. In llapi_getname() don't depend on the cfg_instance being exactly 16 characters long, if this changes in the future. Test-Parameters: clientdistro=ubuntu1804 testlist=sanity Signed-off-by: Andreas Dilger Change-Id: I166de0248af8fe57535628a64bb770a4e03ebbe5 Reviewed-on: https://review.whamcloud.com/33900 Tested-by: Jenkins Reviewed-by: Sebastien Buisson Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/include/obd_class.h | 15 ++++- lustre/llite/llite_lib.c | 48 +++++++++------- lustre/mgc/mgc_request.c | 115 +++++++++++++++++++------------------ lustre/obdclass/obd_config.c | 32 +++++------ lustre/obdclass/obd_mount_server.c | 4 +- lustre/ofd/ofd_dev.c | 25 ++++---- lustre/utils/liblustreapi.c | 40 ++++++++----- 7 files changed, 152 insertions(+), 127 deletions(-) diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h index 8682248..f0fcedb 100644 --- a/lustre/include/obd_class.h +++ b/lustre/include/obd_class.h @@ -189,7 +189,7 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg); /* Passed as data param to class_config_parse_llog */ struct config_llog_instance { - void *cfg_instance; + unsigned long cfg_instance; struct super_block *cfg_sb; struct obd_uuid cfg_uuid; llog_cb_t cfg_callback; @@ -201,6 +201,19 @@ struct config_llog_instance { int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt, char *name, struct config_llog_instance *cfg); +/** + * Generate a unique configuration instance for this mount + * + * Temporary hack to bypass ASLR in 4.15+ kernels, a better fix soon. + * For now, use the same value as before - the superblock pointer value. + * + * Using the client UUID would be an option, but it needs more testing. + */ +static inline unsigned long ll_get_cfg_instance(struct super_block *sb) +{ + return (unsigned long)sb; +} + #define CONFIG_SUB_SPTLRPC 0x01 #define CONFIG_SUB_RECOVER 0x02 #define CONFIG_SUB_PARAMS 0x04 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 4d8ad57..a7e8672 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -1017,6 +1017,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) struct config_llog_instance *cfg; /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */ const int instlen = sizeof(cfg->cfg_instance) * 2 + 2; + unsigned long cfg_instance = ll_get_cfg_instance(sb); char name[MAX_STRING_SIZE]; int md_len = 0; int dt_len = 0; @@ -1025,7 +1026,9 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) int err; ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb); + /* for ASLR, to map between cfg_instance and hashed ptr */ + CDEBUG(D_VFSTRACE, "VFS Op: cfg_instance %s-%016lx (sb %p)\n", + profilenm, cfg_instance, sb); try_module_get(THIS_MODULE); @@ -1042,7 +1045,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) if (err) GOTO(out_free_cfg, err); - err = super_setup_bdi_name(sb, "lustre-%p", sb); + err = super_setup_bdi_name(sb, "lustre-%016lx", cfg_instance); if (err) GOTO(out_free_cfg, err); @@ -1051,14 +1054,14 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) sb->s_d_op = &ll_d_ops; #endif /* Get fsname */ - len = strlen(lsi->lsi_lmd->lmd_profile); - ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-'); + len = strlen(profilenm); + ptr = strrchr(profilenm, '-'); if (ptr && (strcmp(ptr, "-client") == 0)) len -= 7; /* Mount info */ - snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len, - lsi->lsi_lmd->lmd_profile, sb); + snprintf(name, MAX_STRING_SIZE, "%.*s-%016lx", len, + profilenm, cfg_instance); /* Call ll_debugfs_register_super() before lustre_process_log() * so that "llite.*.*" params can be processed correctly. @@ -1070,11 +1073,10 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) err = 0; } - /* Generate a string unique to this super, in case some joker tries - * to mount the same fs at two mount points. - * Use the address of the super itself. + /* The cfg_instance is a value unique to this super, in case some + * joker tries to mount the same fs at two mount points. */ - cfg->cfg_instance = sb; + cfg->cfg_instance = cfg_instance; cfg->cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid; cfg->cfg_callback = class_config_llog_handler; cfg->cfg_sub_clds = CONFIG_SUB_CLIENT; @@ -1098,13 +1100,13 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) OBD_ALLOC(dt, dt_len); if (!dt) GOTO(out_profile, err = -ENOMEM); - snprintf(dt, dt_len - 1, "%s-%p", lprof->lp_dt, cfg->cfg_instance); + snprintf(dt, dt_len - 1, "%s-%016lx", lprof->lp_dt, cfg_instance); md_len = strlen(lprof->lp_md) + instlen + 2; OBD_ALLOC(md, md_len); if (!md) GOTO(out_free_dt, err = -ENOMEM); - snprintf(md, md_len - 1, "%s-%p", lprof->lp_md, cfg->cfg_instance); + snprintf(md, md_len - 1, "%s-%016lx", lprof->lp_md, cfg_instance); /* connections, registrations, sb setup */ err = client_common_fill_super(sb, md, dt, mnt); @@ -1139,23 +1141,26 @@ out_free_cfg: void ll_put_super(struct super_block *sb) { struct config_llog_instance cfg, params_cfg; - struct obd_device *obd; - struct lustre_sb_info *lsi = s2lsi(sb); - struct ll_sb_info *sbi = ll_s2sbi(sb); - char *profilenm = get_profile_name(sb); + struct obd_device *obd; + struct lustre_sb_info *lsi = s2lsi(sb); + struct ll_sb_info *sbi = ll_s2sbi(sb); + char *profilenm = get_profile_name(sb); + unsigned long cfg_instance = ll_get_cfg_instance(sb); long ccc_count; int next, force = 1, rc = 0; - ENTRY; + ENTRY; if (!sbi) GOTO(out_no_sbi, 0); - CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm); + /* Should replace instance_id with something better for ASLR */ + CDEBUG(D_VFSTRACE, "VFS Op: cfg_instance %s-%016lx (sb %p)\n", + profilenm, cfg_instance, sb); - cfg.cfg_instance = sb; - lustre_end_log(sb, profilenm, &cfg); + cfg.cfg_instance = cfg_instance; + lustre_end_log(sb, profilenm, &cfg); - params_cfg.cfg_instance = sb; + params_cfg.cfg_instance = cfg_instance; lustre_end_log(sb, PARAMS_FILENAME, ¶ms_cfg); if (sbi->ll_md_exp) { @@ -1176,7 +1181,6 @@ void ll_put_super(struct super_block *sb) if (force == 0 && rc != -EINTR) LASSERTF(ccc_count == 0, "count: %li\n", ccc_count); - /* We need to set force before the lov_disconnect in lustre_common_put_super, since l_d cleans up osc's as well. */ if (force) { diff --git a/lustre/mgc/mgc_request.c b/lustre/mgc/mgc_request.c index 430b01b..896a2e2 100644 --- a/lustre/mgc/mgc_request.c +++ b/lustre/mgc/mgc_request.c @@ -170,18 +170,18 @@ static struct config_llog_data *config_log_find(char *logname, struct config_llog_instance *cfg) { - struct config_llog_data *cld; - struct config_llog_data *found = NULL; - void * instance; - ENTRY; + struct config_llog_data *cld; + struct config_llog_data *found = NULL; + unsigned long cfg_instance; - LASSERT(logname != NULL); + ENTRY; + LASSERT(logname != NULL); - instance = cfg ? cfg->cfg_instance : NULL; + cfg_instance = cfg ? cfg->cfg_instance : 0; spin_lock(&config_list_lock); list_for_each_entry(cld, &config_llog_list, cld_list_chain) { - /* check if instance equals */ - if (instance != cld->cld_cfg.cfg_instance) + /* check if cfg_instance is the one we want */ + if (cfg_instance != cld->cld_cfg.cfg_instance) continue; /* instance may be NULL, should check name */ @@ -207,8 +207,8 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd, ENTRY; - CDEBUG(D_MGC, "do adding config log %s:%p\n", logname, - cfg ? cfg->cfg_instance : NULL); + CDEBUG(D_MGC, "do adding config log %s-%016lx\n", logname, + cfg ? cfg->cfg_instance : 0); OBD_ALLOC(cld, sizeof(*cld) + strlen(logname) + 1); if (!cld) @@ -253,47 +253,49 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd, } static struct config_llog_data *config_recover_log_add(struct obd_device *obd, - char *fsname, - struct config_llog_instance *cfg, - struct super_block *sb) + char *fsname, + struct config_llog_instance *cfg, + struct super_block *sb) { - struct config_llog_instance lcfg = *cfg; - struct lustre_sb_info *lsi = s2lsi(sb); - struct config_llog_data *cld; - char logname[32]; + struct config_llog_instance lcfg = *cfg; + struct lustre_sb_info *lsi = s2lsi(sb); + struct config_llog_data *cld; + char logname[32]; if (IS_OST(lsi)) - return NULL; + return NULL; /* for osp-on-ost, see lustre_start_osp() */ if (IS_MDT(lsi) && lcfg.cfg_instance) return NULL; - /* we have to use different llog for clients and mdts for cmd - * where only clients are notified if one of cmd server restarts */ - LASSERT(strlen(fsname) < sizeof(logname) / 2); - strcpy(logname, fsname); + /* We have to use different llog for clients and MDTs for DNE, + * where only clients are notified if one of DNE server restarts. + */ + LASSERT(strlen(fsname) < sizeof(logname) / 2); + strncpy(logname, fsname, sizeof(logname)); if (IS_SERVER(lsi)) { /* mdt */ - LASSERT(lcfg.cfg_instance == NULL); - lcfg.cfg_instance = sb; - strcat(logname, "-mdtir"); - } else { - LASSERT(lcfg.cfg_instance != NULL); - strcat(logname, "-cliir"); - } + LASSERT(lcfg.cfg_instance == 0); + lcfg.cfg_instance = ll_get_cfg_instance(sb); + strncat(logname, "-mdtir", sizeof(logname)); + } else { + LASSERT(lcfg.cfg_instance != 0); + strncat(logname, "-cliir", sizeof(logname)); + } - cld = do_config_log_add(obd, logname, CONFIG_T_RECOVER, &lcfg, sb); - return cld; + cld = do_config_log_add(obd, logname, CONFIG_T_RECOVER, &lcfg, sb); + return cld; } static struct config_llog_data *config_log_find_or_add(struct obd_device *obd, char *logname, struct super_block *sb, int type, struct config_llog_instance *cfg) { - struct config_llog_instance lcfg = *cfg; - struct config_llog_data *cld; + struct config_llog_instance lcfg = *cfg; + struct config_llog_data *cld; - lcfg.cfg_instance = sb != NULL ? (void *)sb : (void *)obd; + /* Note class_config_llog_handler() depends on getting "obd" back */ + lcfg.cfg_instance = sb ? ll_get_cfg_instance(sb) : (unsigned long)obd; cld = config_log_find(logname, &lcfg); if (unlikely(cld != NULL)) @@ -323,7 +325,8 @@ config_log_add(struct obd_device *obd, char *logname, bool locked = false; ENTRY; - CDEBUG(D_MGC, "adding config log %s:%p\n", logname, cfg->cfg_instance); + CDEBUG(D_MGC, "add config log %s-%016lx\n", logname, + cfg->cfg_instance); /* * for each regular log, the depended sptlrpc log name is @@ -1402,34 +1405,34 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, __u64 max_version, void *data, int datalen, bool mne_swab) { - struct config_llog_instance *cfg = &cld->cld_cfg; - struct lustre_sb_info *lsi = s2lsi(cfg->cfg_sb); - struct mgs_nidtbl_entry *entry; - struct lustre_cfg *lcfg; - struct lustre_cfg_bufs bufs; - u64 prev_version = 0; - char *inst; - char *buf; - int bufsz; - int pos; - int rc = 0; - int off = 0; - ENTRY; + struct config_llog_instance *cfg = &cld->cld_cfg; + struct lustre_sb_info *lsi = s2lsi(cfg->cfg_sb); + struct mgs_nidtbl_entry *entry; + struct lustre_cfg *lcfg; + struct lustre_cfg_bufs bufs; + u64 prev_version = 0; + char *inst; + char *buf; + int bufsz; + int pos; + int rc = 0; + int off = 0; - LASSERT(cfg->cfg_instance != NULL); - LASSERT(cfg->cfg_sb == cfg->cfg_instance); + ENTRY; + LASSERT(cfg->cfg_instance != 0); + LASSERT(ll_get_cfg_instance(cfg->cfg_sb) == cfg->cfg_instance); OBD_ALLOC(inst, PAGE_SIZE); if (inst == NULL) RETURN(-ENOMEM); if (!IS_SERVER(lsi)) { - pos = snprintf(inst, PAGE_SIZE, "%p", cfg->cfg_instance); + pos = snprintf(inst, PAGE_SIZE, "%016lx", cfg->cfg_instance); if (pos >= PAGE_SIZE) { OBD_FREE(inst, PAGE_SIZE); return -E2BIG; } - } else { + } else { LASSERT(IS_MDT(lsi)); rc = server_name2svname(lsi->lsi_svname, inst, NULL, PAGE_SIZE); @@ -2047,12 +2050,12 @@ restart: mutex_lock(&cld->cld_lock); if (cld->cld_stopping) { mutex_unlock(&cld->cld_lock); - RETURN(0); - } + RETURN(0); + } - OBD_FAIL_TIMEOUT(OBD_FAIL_MGC_PAUSE_PROCESS_LOG, 20); + OBD_FAIL_TIMEOUT(OBD_FAIL_MGC_PAUSE_PROCESS_LOG, 20); - CDEBUG(D_MGC, "Process log %s:%p from %d\n", cld->cld_logname, + CDEBUG(D_MGC, "Process log %s-%016lx from %d\n", cld->cld_logname, cld->cld_cfg.cfg_instance, cld->cld_cfg.cfg_last_idx + 1); /* Get the cfg lock on the llog */ diff --git a/lustre/obdclass/obd_config.c b/lustre/obdclass/obd_config.c index 8d03b7b..1c02fd6 100644 --- a/lustre/obdclass/obd_config.c +++ b/lustre/obdclass/obd_config.c @@ -806,7 +806,7 @@ static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg) static LIST_HEAD(lustre_profile_list); static DEFINE_SPINLOCK(lustre_profile_list_lock); -struct lustre_profile *class_get_profile(const char * prof) +struct lustre_profile *class_get_profile(const char *prof) { struct lustre_profile *lprof; @@ -1636,8 +1636,7 @@ int class_config_llog_handler(const struct lu_env *env, */ if (!(cfg->cfg_flags & CFG_F_MARKER) && (lcfg->lcfg_command != LCFG_MARKER)) { - CWARN("Config not inside markers, ignoring! " - "(inst: %p, uuid: %s, flags: %#x)\n", + CWARN("Skip config outside markers, (inst: %016lx, uuid: %s, flags: %#x)\n", cfg->cfg_instance, cfg->cfg_uuid.uuid, cfg->cfg_flags); cfg->cfg_flags |= CFG_F_SKIP; @@ -1718,7 +1717,7 @@ int class_config_llog_handler(const struct lu_env *env, OBD_ALLOC(inst_name, inst_len); if (inst_name == NULL) GOTO(out, rc = -ENOMEM); - snprintf(inst_name, inst_len, "%s-%p", + snprintf(inst_name, inst_len, "%s-%016lx", lustre_cfg_string(lcfg, 0), cfg->cfg_instance); lustre_cfg_bufs_set_string(&bufs, 0, inst_name); @@ -1726,23 +1725,22 @@ int class_config_llog_handler(const struct lu_env *env, lcfg->lcfg_command, inst_name); } - /* we override the llog's uuid for clients, to insure they - are unique */ - if (cfg->cfg_instance != NULL && - lcfg->lcfg_command == LCFG_ATTACH) { + /* override llog UUID for clients, to insure they are unique */ + if (cfg->cfg_instance && lcfg->lcfg_command == LCFG_ATTACH) lustre_cfg_bufs_set_string(&bufs, 2, cfg->cfg_uuid.uuid); - } - /* - * sptlrpc config record, we expect 2 data segments: - * [0]: fs_name/target_name, - * [1]: rule string - * moving them to index [1] and [2], and insert MGC's - * obdname at index [0]. - */ + /* + * sptlrpc config record, we expect 2 data segments: + * [0]: fs_name/target_name, + * [1]: rule string + * moving them to index [1] and [2], and insert MGC's + * obdname at index [0]. + */ if (cfg->cfg_instance && lcfg->lcfg_command == LCFG_SPTLRPC_CONF) { - struct obd_device *obd = cfg->cfg_instance; + /* After ASLR changes cfg_instance this needs fixing */ + /* "obd" is set in config_log_find_or_add() */ + struct obd_device *obd = (void *)cfg->cfg_instance; lustre_cfg_bufs_set(&bufs, 2, bufs.lcfg_buf[1], bufs.lcfg_buflen[1]); diff --git a/lustre/obdclass/obd_mount_server.c b/lustre/obdclass/obd_mount_server.c index 18b3e17..92cf5cc 100644 --- a/lustre/obdclass/obd_mount_server.c +++ b/lustre/obdclass/obd_mount_server.c @@ -934,7 +934,7 @@ static int lustre_disconnect_lwp(struct super_block *sb) GOTO(out, rc = -ENOMEM); /* end log first */ - cfg->cfg_instance = sb; + cfg->cfg_instance = ll_get_cfg_instance(sb); rc = lustre_end_log(sb, logname, cfg); if (rc != 0 && rc != -ENOENT) GOTO(out, rc); @@ -1046,7 +1046,7 @@ static int lustre_start_lwp(struct super_block *sb) GOTO(out, rc = -ENOMEM); cfg->cfg_callback = client_lwp_config_process; - cfg->cfg_instance = sb; + cfg->cfg_instance = ll_get_cfg_instance(sb); rc = lustre_process_log(sb, logname, cfg); /* need to remove config llog from mgc */ lsi->lsi_lwp_started = 1; diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c index 531d95a..a246be6 100644 --- a/lustre/ofd/ofd_dev.c +++ b/lustre/ofd/ofd_dev.c @@ -789,18 +789,19 @@ int ofd_fid_fini(const struct lu_env *env, struct ofd_device *ofd) */ int ofd_fid_init(const struct lu_env *env, struct ofd_device *ofd) { - struct seq_server_site *ss = &ofd->ofd_seq_site; - struct lu_device *lu = &ofd->ofd_dt_dev.dd_lu_dev; - char *obd_name = ofd_name(ofd); - char *name = NULL; - int rc = 0; + struct seq_server_site *ss = &ofd->ofd_seq_site; + struct lu_device *lu = &ofd->ofd_dt_dev.dd_lu_dev; + char *obd_name = ofd_name(ofd); + char *name = NULL; + int len = strlen(obd_name) + 7; + int rc = 0; ss = &ofd->ofd_seq_site; lu->ld_site->ld_seq_site = ss; ss->ss_lu = lu->ld_site; ss->ss_node_id = ofd->ofd_lut.lut_lsd.lsd_osd_index; - OBD_ALLOC(name, sizeof(obd_name) * 2 + 10); + OBD_ALLOC(name, len); if (name == NULL) return -ENOMEM; @@ -811,7 +812,7 @@ int ofd_fid_init(const struct lu_env *env, struct ofd_device *ofd) rc = seq_server_init(env, ss->ss_server_seq, ofd->ofd_osd, obd_name, LUSTRE_SEQ_SERVER, ss); if (rc) { - CERROR("%s : seq server init error %d\n", obd_name, rc); + CERROR("%s: seq server init error: rc = %d\n", obd_name, rc); GOTO(out_server, rc); } ss->ss_server_seq->lss_space.lsr_index = ss->ss_node_id; @@ -820,15 +821,11 @@ int ofd_fid_init(const struct lu_env *env, struct ofd_device *ofd) if (ss->ss_client_seq == NULL) GOTO(out_server, rc = -ENOMEM); - /* - * It always printed as "%p", so that the name is unique in the kernel, - * even if the filesystem is mounted twice. So sizeof(.) * 2 is enough. - */ - snprintf(name, sizeof(obd_name) * 2 + 7, "%p-super", obd_name); + snprintf(name, len, "%s-super", obd_name); rc = seq_client_init(ss->ss_client_seq, NULL, LUSTRE_SEQ_DATA, name, NULL); if (rc) { - CERROR("%s : seq client init error %d\n", obd_name, rc); + CERROR("%s: seq client init error: rc = %d\n", obd_name, rc); GOTO(out_client, rc); } @@ -845,7 +842,7 @@ out_server: ss->ss_server_seq = NULL; } out_name: - OBD_FREE(name, sizeof(obd_name) * 2 + 10); + OBD_FREE(name, len); return rc; } diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index ad598b2..ea286c3 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -1344,26 +1344,36 @@ int llapi_search_rootpath(char *pathname, const char *fsname) int llapi_getname(const char *path, char *buf, size_t size) { - struct obd_uuid uuid_buf; - char *uuid = uuid_buf.uuid; - int rc, nr; + struct obd_uuid uuid_buf; + char *uuid = uuid_buf.uuid; + char *cfg_instance; + int rc, len, fsname_len; - memset(&uuid_buf, 0, sizeof(uuid_buf)); - rc = llapi_file_get_lov_uuid(path, &uuid_buf); - if (rc) - return rc; + memset(&uuid_buf, 0, sizeof(uuid_buf)); + rc = llapi_file_get_lov_uuid(path, &uuid_buf); + if (rc) + return rc; - /* We want to turn lustre-clilov-ffff88002738bc00 into - * lustre-ffff88002738bc00. */ + /* + * We want to turn testfs-clilov-ffff88002738bc00 into + * testfs-ffff88002738bc00 in a portable way that doesn't depend + * on what is after "-clilov-" as it may change in the future. + * Unfortunately, the "fsname" part may contain a dash, so we + * can't just skip to the first dash, and the "instance" may be a + * UUID in the future, so we can't necessarily go to the last dash. + */ + cfg_instance = strstr(uuid, "-clilov-"); + if (!cfg_instance) + return -EINVAL; - nr = snprintf(buf, size, "%.*s-%s", - (int) (strlen(uuid) - 24), uuid, - uuid + strlen(uuid) - 16); + fsname_len = cfg_instance - uuid; + cfg_instance += strlen("-clilov-"); + len = snprintf(buf, size, "%.*s-%s", fsname_len, uuid, cfg_instance); - if (nr >= size) - rc = -ENAMETOOLONG; + if (len >= size) + rc = -ENAMETOOLONG; - return rc; + return rc; } /** -- 1.8.3.1