ses: close potential registration race

The slot and address fields have a small window of instability when
userspace can read them before initialization. Separate
enclosure_component
allocation from registration.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Song Liu <songliubraving@fb.com>
Reviewed-by: Jens Axboe <axboe@fb.com>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Dan Williams 2014-12-30 14:46:14 -08:00 committed by Christoph Hellwig
parent acd6d73826
commit ed09dcc8bd
3 changed files with 43 additions and 20 deletions

View File

@ -273,27 +273,26 @@ enclosure_component_find_by_name(struct enclosure_device *edev,
static const struct attribute_group *enclosure_component_groups[];
/**
* enclosure_component_register - add a particular component to an enclosure
* enclosure_component_alloc - prepare a new enclosure component
* @edev: the enclosure to add the component
* @num: the device number
* @type: the type of component being added
* @name: an optional name to appear in sysfs (leave NULL if none)
*
* Registers the component. The name is optional for enclosures that
* give their components a unique name. If not, leave the field NULL
* and a name will be assigned.
* The name is optional for enclosures that give their components a unique
* name. If not, leave the field NULL and a name will be assigned.
*
* Returns a pointer to the enclosure component or an error.
*/
struct enclosure_component *
enclosure_component_register(struct enclosure_device *edev,
unsigned int number,
enum enclosure_component_type type,
const char *name)
enclosure_component_alloc(struct enclosure_device *edev,
unsigned int number,
enum enclosure_component_type type,
const char *name)
{
struct enclosure_component *ecomp;
struct device *cdev;
int err, i;
int i;
char newname[COMPONENT_NAME_SIZE];
if (number >= edev->components)
@ -327,14 +326,30 @@ enclosure_component_register(struct enclosure_device *edev,
cdev->release = enclosure_component_release;
cdev->groups = enclosure_component_groups;
return ecomp;
}
EXPORT_SYMBOL_GPL(enclosure_component_alloc);
/**
* enclosure_component_register - publishes an initialized enclosure component
* @ecomp: component to add
*
* Returns 0 on successful registration, releases the component otherwise
*/
int enclosure_component_register(struct enclosure_component *ecomp)
{
struct device *cdev;
int err;
cdev = &ecomp->cdev;
err = device_register(cdev);
if (err) {
ecomp->number = -1;
put_device(cdev);
return ERR_PTR(err);
return err;
}
return ecomp;
return 0;
}
EXPORT_SYMBOL_GPL(enclosure_component_register);

View File

@ -423,16 +423,23 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {
if (create)
ecomp = enclosure_component_register(edev,
components++,
type_ptr[0],
name);
ecomp = enclosure_component_alloc(
edev,
components++,
type_ptr[0],
name);
else
ecomp = &edev->component[components++];
if (!IS_ERR(ecomp) && addl_desc_ptr)
ses_process_descriptor(ecomp,
addl_desc_ptr);
if (!IS_ERR(ecomp)) {
if (addl_desc_ptr)
ses_process_descriptor(
ecomp,
addl_desc_ptr);
if (create)
enclosure_component_register(
ecomp);
}
}
if (desc_ptr)
desc_ptr += len;

View File

@ -120,8 +120,9 @@ enclosure_register(struct device *, const char *, int,
struct enclosure_component_callbacks *);
void enclosure_unregister(struct enclosure_device *);
struct enclosure_component *
enclosure_component_register(struct enclosure_device *, unsigned int,
enum enclosure_component_type, const char *);
enclosure_component_alloc(struct enclosure_device *, unsigned int,
enum enclosure_component_type, const char *);
int enclosure_component_register(struct enclosure_component *);
int enclosure_add_device(struct enclosure_device *enclosure, int component,
struct device *dev);
int enclosure_remove_device(struct enclosure_device *, struct device *);