mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 16:49:22 +00:00
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:
parent
acd6d73826
commit
ed09dcc8bd
3 changed files with 43 additions and 20 deletions
|
@ -273,27 +273,26 @@ enclosure_component_find_by_name(struct enclosure_device *edev,
|
||||||
static const struct attribute_group *enclosure_component_groups[];
|
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
|
* @edev: the enclosure to add the component
|
||||||
* @num: the device number
|
* @num: the device number
|
||||||
* @type: the type of component being added
|
* @type: the type of component being added
|
||||||
* @name: an optional name to appear in sysfs (leave NULL if none)
|
* @name: an optional name to appear in sysfs (leave NULL if none)
|
||||||
*
|
*
|
||||||
* Registers the component. The name is optional for enclosures that
|
* The name is optional for enclosures that give their components a unique
|
||||||
* give their components a unique name. If not, leave the field NULL
|
* name. If not, leave the field NULL and a name will be assigned.
|
||||||
* and a name will be assigned.
|
|
||||||
*
|
*
|
||||||
* Returns a pointer to the enclosure component or an error.
|
* Returns a pointer to the enclosure component or an error.
|
||||||
*/
|
*/
|
||||||
struct enclosure_component *
|
struct enclosure_component *
|
||||||
enclosure_component_register(struct enclosure_device *edev,
|
enclosure_component_alloc(struct enclosure_device *edev,
|
||||||
unsigned int number,
|
unsigned int number,
|
||||||
enum enclosure_component_type type,
|
enum enclosure_component_type type,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
struct enclosure_component *ecomp;
|
struct enclosure_component *ecomp;
|
||||||
struct device *cdev;
|
struct device *cdev;
|
||||||
int err, i;
|
int i;
|
||||||
char newname[COMPONENT_NAME_SIZE];
|
char newname[COMPONENT_NAME_SIZE];
|
||||||
|
|
||||||
if (number >= edev->components)
|
if (number >= edev->components)
|
||||||
|
@ -327,14 +326,30 @@ enclosure_component_register(struct enclosure_device *edev,
|
||||||
cdev->release = enclosure_component_release;
|
cdev->release = enclosure_component_release;
|
||||||
cdev->groups = enclosure_component_groups;
|
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);
|
err = device_register(cdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
ecomp->number = -1;
|
ecomp->number = -1;
|
||||||
put_device(cdev);
|
put_device(cdev);
|
||||||
return ERR_PTR(err);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ecomp;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(enclosure_component_register);
|
EXPORT_SYMBOL_GPL(enclosure_component_register);
|
||||||
|
|
||||||
|
|
|
@ -423,16 +423,23 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
|
||||||
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {
|
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {
|
||||||
|
|
||||||
if (create)
|
if (create)
|
||||||
ecomp = enclosure_component_register(edev,
|
ecomp = enclosure_component_alloc(
|
||||||
|
edev,
|
||||||
components++,
|
components++,
|
||||||
type_ptr[0],
|
type_ptr[0],
|
||||||
name);
|
name);
|
||||||
else
|
else
|
||||||
ecomp = &edev->component[components++];
|
ecomp = &edev->component[components++];
|
||||||
|
|
||||||
if (!IS_ERR(ecomp) && addl_desc_ptr)
|
if (!IS_ERR(ecomp)) {
|
||||||
ses_process_descriptor(ecomp,
|
if (addl_desc_ptr)
|
||||||
|
ses_process_descriptor(
|
||||||
|
ecomp,
|
||||||
addl_desc_ptr);
|
addl_desc_ptr);
|
||||||
|
if (create)
|
||||||
|
enclosure_component_register(
|
||||||
|
ecomp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (desc_ptr)
|
if (desc_ptr)
|
||||||
desc_ptr += len;
|
desc_ptr += len;
|
||||||
|
|
|
@ -120,8 +120,9 @@ enclosure_register(struct device *, const char *, int,
|
||||||
struct enclosure_component_callbacks *);
|
struct enclosure_component_callbacks *);
|
||||||
void enclosure_unregister(struct enclosure_device *);
|
void enclosure_unregister(struct enclosure_device *);
|
||||||
struct enclosure_component *
|
struct enclosure_component *
|
||||||
enclosure_component_register(struct enclosure_device *, unsigned int,
|
enclosure_component_alloc(struct enclosure_device *, unsigned int,
|
||||||
enum enclosure_component_type, const char *);
|
enum enclosure_component_type, const char *);
|
||||||
|
int enclosure_component_register(struct enclosure_component *);
|
||||||
int enclosure_add_device(struct enclosure_device *enclosure, int component,
|
int enclosure_add_device(struct enclosure_device *enclosure, int component,
|
||||||
struct device *dev);
|
struct device *dev);
|
||||||
int enclosure_remove_device(struct enclosure_device *, struct device *);
|
int enclosure_remove_device(struct enclosure_device *, struct device *);
|
||||||
|
|
Loading…
Reference in a new issue