Skip to content
Open
14 changes: 9 additions & 5 deletions drivers/scsi/ses.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,15 +559,19 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
struct enclosure_component *ecomp;

if (desc_ptr) {
if (desc_ptr >= buf + page7_len) {
if (desc_ptr + 3 >= buf + page7_len) {
desc_ptr = NULL;
} else {
len = (desc_ptr[2] << 8) + desc_ptr[3];
desc_ptr += 4;
/* Add trailing zero - pushes into
* reserved space */
desc_ptr[len] = '\0';
name = desc_ptr;
if (desc_ptr + len > buf + page7_len)
desc_ptr = NULL;
else {
/* Add trailing zero - pushes into
* reserved space */
desc_ptr[len] = '\0';
name = desc_ptr;
}
}
}
if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
req->request.actual = 0;
req->request.status = -EINPROGRESS;
req->epnum = dep->number;
req->status = DWC3_REQUEST_STATUS_QUEUED;

list_add_tail(&req->list, &dep->pending_list);

Expand Down
7 changes: 7 additions & 0 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
{
struct dwc3 *dwc = dep->dwc;

/*
* The request might have been processed and completed while the
* spinlock was released. Skip processing if already completed.
*/
if (req->status == DWC3_REQUEST_STATUS_COMPLETED)
return;

dwc3_gadget_del_and_unmap_request(dep, req, status);
req->status = DWC3_REQUEST_STATUS_COMPLETED;

Expand Down
18 changes: 18 additions & 0 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,7 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifs_tcon *tcon;
bool rehash = false;
unsigned int xid;
int rc, tmprc;
int retry_count = 0;
Expand All @@ -2132,6 +2133,17 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
if (unlikely(cifs_forced_shutdown(cifs_sb)))
return -EIO;

/*
* Prevent any concurrent opens on the target by unhashing the dentry.
* VFS already unhashes the target when renaming directories.
*/
if (d_is_positive(target_dentry) && !d_is_dir(target_dentry)) {
if (!d_unhashed(target_dentry)) {
d_drop(target_dentry);
rehash = true;
}
}

tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
Expand Down Expand Up @@ -2171,6 +2183,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
}
}

if (!rc)
rehash = false;
/*
* No-replace is the natural behavior for CIFS, so skip unlink hacks.
*/
Expand Down Expand Up @@ -2229,6 +2243,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
goto cifs_rename_exit;
rc = cifs_do_rename(xid, source_dentry, from_name,
target_dentry, to_name);
if (!rc)
rehash = false;
}

/* force revalidate to go get info when needed */
Expand All @@ -2238,6 +2254,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
target_dir->i_mtime = current_time(source_dir);

cifs_rename_exit:
if (rehash)
d_rehash(target_dentry);
kfree(info_buf_source);
free_dentry_path(page2);
free_dentry_path(page1);
Expand Down
20 changes: 15 additions & 5 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -4141,10 +4141,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
}
status = nfs_ok;
if (conf) {
old = unconf;
unhash_client_locked(old);
nfsd4_change_callback(conf, &unconf->cl_cb_conn);
} else {
if (get_client_locked(conf) == nfs_ok) {
old = unconf;
unhash_client_locked(old);
nfsd4_change_callback(conf, &unconf->cl_cb_conn);
} else {
conf = NULL;
}
}

if (!conf) {
old = find_confirmed_client_by_name(&unconf->cl_name, nn);
if (old) {
status = nfserr_clid_inuse;
Expand All @@ -4161,10 +4167,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
}
trace_nfsd_clid_replaced(&old->cl_clientid);
}
status = get_client_locked(unconf);
if (status != nfs_ok) {
old = NULL;
goto out;
}
move_to_confirmed(unconf);
conf = unconf;
}
get_client_locked(conf);
spin_unlock(&nn->client_lock);
if (conf == unconf)
fsnotify_dentry(conf->cl_nfsd_info_dentry, FS_MODIFY);
Expand Down
4 changes: 3 additions & 1 deletion fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2378,10 +2378,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
for (i = 0; i < argp->opcnt; i++) {
op = &argp->ops[i];
op->replay = NULL;
op->opdesc = NULL;

if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
return false;
if (nfsd4_opnum_in_range(argp, op)) {
op->opdesc = OPDESC(op);
op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
if (op->status != nfs_ok)
trace_nfsd_compound_decode_err(argp->rqstp,
Expand All @@ -2392,7 +2394,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
op->opnum = OP_ILLEGAL;
op->status = nfserr_op_illegal;
}
op->opdesc = OPDESC(op);

/*
* We'll try to cache the result in the DRC if any one
* op in the compound wants to be cached:
Expand Down
21 changes: 21 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,27 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_role(struct hci_dev *hdev,
__u8 type, __u8 role,
bdaddr_t *ba)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;

rcu_read_lock();

list_for_each_entry_rcu(c, &h->list, list) {
if (c->type == type && c->role == role && !bacmp(&c->dst, ba)) {
rcu_read_unlock();
return c;
}
}

rcu_read_unlock();

return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev,
bdaddr_t *ba,
__u8 ba_type)
Expand Down
26 changes: 23 additions & 3 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -3088,8 +3088,18 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,

hci_dev_lock(hdev);

/* Check for existing connection:
*
* 1. If it doesn't exist then it must be receiver/slave role.
* 2. If it does exist confirm that it is connecting/BT_CONNECT in case
* of initiator/master role since there could be a collision where
* either side is attempting to connect or something like a fuzzing
* testing is trying to play tricks to destroy the hcon object before
* it even attempts to connect (e.g. hcon->state == BT_OPEN).
*/
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
if (!conn ||
(conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
/* In case of error status and there is no connection pending
* just unlock as there is nothing to cleanup.
*/
Expand Down Expand Up @@ -5803,8 +5813,18 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
*/
hci_dev_clear_flag(hdev, HCI_LE_ADV);

conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
if (!conn) {
/* Check for existing connection:
*
* 1. If it doesn't exist then use the role to create a new object.
* 2. If it does exist confirm that it is connecting/BT_CONNECT in case
* of initiator/master role since there could be a collision where
* either side is attempting to connect or something like a fuzzing
* testing is trying to play tricks to destroy the hcon object before
* it even attempts to connect (e.g. hcon->state == BT_OPEN).
*/
conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr);
if (!conn ||
(conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
/* In case of error status and there is no connection pending
* just unlock as there is nothing to cleanup.
*/
Expand Down
53 changes: 32 additions & 21 deletions net/ceph/ceph_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,42 +785,53 @@ void ceph_reset_client_addr(struct ceph_client *client)
}
EXPORT_SYMBOL(ceph_reset_client_addr);

/*
* true if we have the mon map (and have thus joined the cluster)
*/
static bool have_mon_and_osd_map(struct ceph_client *client)
{
return client->monc.monmap && client->monc.monmap->epoch &&
client->osdc.osdmap && client->osdc.osdmap->epoch;
}

/*
* mount: join the ceph cluster, and open root directory.
*/
int __ceph_open_session(struct ceph_client *client, unsigned long started)
{
unsigned long timeout = client->options->mount_timeout;
long err;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
long timeout = ceph_timeout_jiffies(client->options->mount_timeout);
bool have_monmap, have_osdmap;
int err;

/* open session, and wait for mon and osd maps */
err = ceph_monc_open_session(&client->monc);
if (err < 0)
return err;

while (!have_mon_and_osd_map(client)) {
if (timeout && time_after_eq(jiffies, started + timeout))
return -ETIMEDOUT;
add_wait_queue(&client->auth_wq, &wait);
for (;;) {
mutex_lock(&client->monc.mutex);
err = client->auth_err;
have_monmap = client->monc.monmap && client->monc.monmap->epoch;
mutex_unlock(&client->monc.mutex);

down_read(&client->osdc.lock);
have_osdmap = client->osdc.osdmap && client->osdc.osdmap->epoch;
up_read(&client->osdc.lock);

if (err || (have_monmap && have_osdmap))
break;

if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
}

if (!timeout) {
err = -ETIMEDOUT;
break;
}

/* wait */
dout("mount waiting for mon_map\n");
err = wait_event_interruptible_timeout(client->auth_wq,
have_mon_and_osd_map(client) || (client->auth_err < 0),
ceph_timeout_jiffies(timeout));
if (err < 0)
return err;
if (client->auth_err < 0)
return client->auth_err;
timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
}
remove_wait_queue(&client->auth_wq, &wait);

if (err)
return err;

pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
&client->fsid);
Expand Down
14 changes: 10 additions & 4 deletions net/ceph/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ static int monmap_show(struct seq_file *s, void *p)
int i;
struct ceph_client *client = s->private;

mutex_lock(&client->monc.mutex);
if (client->monc.monmap == NULL)
return 0;
goto out_unlock;

seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
for (i = 0; i < client->monc.monmap->num_mon; i++) {
Expand All @@ -48,6 +49,9 @@ static int monmap_show(struct seq_file *s, void *p)
ENTITY_NAME(inst->name),
ceph_pr_addr(&inst->addr));
}

out_unlock:
mutex_unlock(&client->monc.mutex);
return 0;
}

Expand All @@ -56,13 +60,14 @@ static int osdmap_show(struct seq_file *s, void *p)
int i;
struct ceph_client *client = s->private;
struct ceph_osd_client *osdc = &client->osdc;
struct ceph_osdmap *map = osdc->osdmap;
struct ceph_osdmap *map;
struct rb_node *n;

down_read(&osdc->lock);
map = osdc->osdmap;
if (map == NULL)
return 0;
goto out_unlock;

down_read(&osdc->lock);
seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch,
osdc->epoch_barrier, map->flags);

Expand Down Expand Up @@ -131,6 +136,7 @@ static int osdmap_show(struct seq_file *s, void *p)
seq_printf(s, "]\n");
}

out_unlock:
up_read(&osdc->lock);
return 0;
}
Expand Down
Loading