Skip to content

Commit

Permalink
Merge branch android-msm-sunfish-4.14-android12 (android-12.0.0_r0.13)
Browse files Browse the repository at this point in the history
sync b1e89e6 Merge branch 'android-msm-pixel-4.14-sc-security' into android-msm-pixel-4.14-sc

Nov 2021.1

Signed-off-by: engstk <[email protected]>
  • Loading branch information
engstk committed Nov 2, 2021
1 parent 9905e43 commit 5a06261
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 157 deletions.
13 changes: 8 additions & 5 deletions drivers/media/platform/msm/npu/npu_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1654,7 +1654,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
int32_t npu_host_unload_network(struct npu_client *client,
struct msm_npu_unload_network_ioctl *unload)
{
int ret = 0;
int ret = 0, retry_cnt = 1;
struct npu_device *npu_dev = client->npu_dev;
struct ipc_cmd_unload_pkt unload_packet;
struct npu_network *network;
Expand Down Expand Up @@ -1690,6 +1690,7 @@ int32_t npu_host_unload_network(struct npu_client *client,
unload_packet.header.flags = 0;
unload_packet.network_hdl = (uint32_t)network->network_hdl;

retry:
/* NPU_IPC_CMD_UNLOAD will go onto IPC_QUEUE_APPS_EXEC */
reinit_completion(&network->cmd_done);
ret = npu_send_network_cmd(npu_dev, network, &unload_packet, false);
Expand All @@ -1698,13 +1699,15 @@ int32_t npu_host_unload_network(struct npu_client *client,
pr_err("NPU_IPC_CMD_UNLOAD sent failed: %d\n", ret);
/*
* If another command is running on this network,
* don't free_network now.
* retry after 500ms.
*/
if (ret == -EBUSY) {
if ((ret == -EBUSY) && (retry_cnt > 0)) {
pr_err("Network is running, retry later\n");
network_put(network);
mutex_unlock(&host_ctx->lock);
return ret;
retry_cnt--;
msleep(500);
mutex_lock(&host_ctx->lock);
goto retry;
}
goto free_network;
}
Expand Down
56 changes: 28 additions & 28 deletions drivers/usb/gadget/function/f_cdev.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2011, 2013-2021, The Linux Foundation. All rights reserved.
* Linux Foundation chooses to take subject only to the GPLv2 license terms,
* and distributes only under these terms.
*
Expand Down Expand Up @@ -94,7 +94,7 @@ struct cserial {

struct f_cdev {
struct cdev fcdev_cdev;
struct device *dev;
struct device dev;
unsigned int port_num;
char name[sizeof(DEVICE_NAME) + 2];
int minor;
Expand Down Expand Up @@ -953,13 +953,16 @@ static void cser_free_inst(struct usb_function_instance *fi)
opts = container_of(fi, struct f_cdev_opts, func_inst);

if (opts->port) {
device_destroy(fcdev_classp, MKDEV(major, opts->port->minor));
cdev_del(&opts->port->fcdev_cdev);
cdev_device_del(&opts->port->fcdev_cdev, &opts->port->dev);
mutex_lock(&chardev_ida_lock);
ida_simple_remove(&chardev_ida, opts->port->minor);
mutex_unlock(&chardev_ida_lock);
usb_cser_debugfs_exit(opts->port);
put_device(&opts->port->dev);
}

usb_cser_chardev_deinit();
kfree(opts->func_name);
kfree(opts->port);
kfree(opts);
}

Expand Down Expand Up @@ -1181,13 +1184,10 @@ int f_cdev_open(struct inode *inode, struct file *file)
struct f_cdev *port;

port = container_of(inode->i_cdev, struct f_cdev, fcdev_cdev);
if (!port) {
pr_err("Port is NULL.\n");
return -EINVAL;
}

if (port && port->port_open) {
get_device(&port->dev);
if (port->port_open) {
pr_err("port is already opened.\n");
put_device(&port->dev);
return -EBUSY;
}

Expand All @@ -1197,6 +1197,7 @@ int f_cdev_open(struct inode *inode, struct file *file)
port->is_connected);
if (ret) {
pr_debug("open interrupted.\n");
put_device(&port->dev);
return ret;
}

Expand All @@ -1216,16 +1217,12 @@ int f_cdev_release(struct inode *inode, struct file *file)
struct f_cdev *port;

port = file->private_data;
if (!port) {
pr_err("port is NULL.\n");
return -EINVAL;
}

spin_lock_irqsave(&port->port_lock, flags);
port->port_open = false;
port->cbits_updated = false;
spin_unlock_irqrestore(&port->port_lock, flags);
pr_debug("port(%s)(%pK) is closed.\n", port->name, port);
put_device(&port->dev);

return 0;
}
Expand Down Expand Up @@ -1830,11 +1827,17 @@ static void usb_cser_debugfs_exit(struct f_cdev *port)
debugfs_remove_recursive(port->debugfs_root);
}

static void cdev_device_release(struct device *dev)
{
struct f_cdev *port = container_of(dev, struct f_cdev, dev);

pr_debug("Free cdev port(%d)\n", port->port_num);
kfree(port);
}

static struct f_cdev *f_cdev_alloc(char *func_name, int portno)
{
int ret;
dev_t dev;
struct device *device;
struct f_cdev *port;

port = kzalloc(sizeof(struct f_cdev), GFP_KERNEL);
Expand Down Expand Up @@ -1885,27 +1888,24 @@ static struct f_cdev *f_cdev_alloc(char *func_name, int portno)

/* create char device */
cdev_init(&port->fcdev_cdev, &f_cdev_fops);
dev = MKDEV(major, port->minor);
ret = cdev_add(&port->fcdev_cdev, dev, 1);
device_initialize(&port->dev);
port->dev.class = fcdev_classp;
port->dev.parent = NULL;
port->dev.release = cdev_device_release;
port->dev.devt = MKDEV(major, port->minor);
dev_set_name(&port->dev, port->name);
ret = cdev_device_add(&port->fcdev_cdev, &port->dev);
if (ret) {
pr_err("Failed to add cdev for port(%s)\n", port->name);
goto err_cdev_add;
}

device = device_create(fcdev_classp, NULL, dev, NULL, port->name);
if (IS_ERR(device)) {
ret = PTR_ERR(device);
goto err_create_dev;
}

usb_cser_debugfs_init(port);

pr_info("port_name:%s (%pK) portno:(%d)\n",
port->name, port, port->port_num);
return port;

err_create_dev:
cdev_del(&port->fcdev_cdev);
err_cdev_add:
destroy_workqueue(port->fcdev_wq);
err_get_ida:
Expand Down
3 changes: 3 additions & 0 deletions fs/seq_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ static void seq_set_overflow(struct seq_file *m)

static void *seq_buf_alloc(unsigned long size)
{
if (unlikely(size > MAX_RW_COUNT))
return NULL;

return kvmalloc(size, GFP_KERNEL);
}

Expand Down
1 change: 1 addition & 0 deletions include/net/af_unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

void unix_inflight(struct user_struct *user, struct file *fp);
void unix_notinflight(struct user_struct *user, struct file *fp);
void unix_destruct_scm(struct sk_buff *skb);
void unix_gc(void);
void wait_for_unix_gc(void);
struct sock *unix_get_socket(struct file *filp);
Expand Down
2 changes: 1 addition & 1 deletion net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ obj-$(CONFIG_WIREGUARD) += wireguard/
obj-$(CONFIG_INET) += ipv4/
obj-$(CONFIG_TLS) += tls/
obj-$(CONFIG_XFRM) += xfrm/
obj-$(CONFIG_UNIX) += unix/
obj-$(CONFIG_UNIX_SCM) += unix/
obj-$(CONFIG_NET) += ipv6/
obj-$(CONFIG_PACKET) += packet/
obj-$(CONFIG_NET_KEY) += key/
Expand Down
5 changes: 5 additions & 0 deletions net/unix/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ config UNIX

Say Y unless you know what you are doing.

config UNIX_SCM
bool
depends on UNIX
default y

config UNIX_DIAG
tristate "UNIX: socket monitoring interface"
depends on UNIX
Expand Down
2 changes: 2 additions & 0 deletions net/unix/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ unix-$(CONFIG_SYSCTL) += sysctl_net_unix.o

obj-$(CONFIG_UNIX_DIAG) += unix_diag.o
unix_diag-y := diag.o

obj-$(CONFIG_UNIX_SCM) += scm.o
102 changes: 45 additions & 57 deletions net/unix/af_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@
#include <linux/freezer.h>
#include <linux/file.h>

#include "scm.h"

struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
EXPORT_SYMBOL_GPL(unix_socket_table);
DEFINE_SPINLOCK(unix_table_lock);
Expand Down Expand Up @@ -1518,65 +1520,51 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
return err;
}

static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
{
int i;

scm->fp = UNIXCB(skb).fp;
UNIXCB(skb).fp = NULL;

for (i = scm->fp->count-1; i >= 0; i--)
unix_notinflight(scm->fp->user, scm->fp->fp[i]);
}

static void unix_destruct_scm(struct sk_buff *skb)
{
struct scm_cookie scm;
memset(&scm, 0, sizeof(scm));
scm.pid = UNIXCB(skb).pid;
if (UNIXCB(skb).fp)
unix_detach_fds(&scm, skb);

/* Alas, it calls VFS */
/* So fscking what? fput() had been SMP-safe since the last Summer */
scm_destroy(&scm);
sock_wfree(skb);
}

/*
* The "user->unix_inflight" variable is protected by the garbage
* collection lock, and we just read it locklessly here. If you go
* over the limit, there might be a tiny race in actually noticing
* it across threads. Tough.
*/
static inline bool too_many_unix_fds(struct task_struct *p)
{
struct user_struct *user = current_user();

if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)))
return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
return false;
}

static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
{
int i;

if (too_many_unix_fds(current))
return -ETOOMANYREFS;
scm->fp = scm_fp_dup(UNIXCB(skb).fp);

/*
* Need to duplicate file references for the sake of garbage
* collection. Otherwise a socket in the fps might become a
* candidate for GC while the skb is not yet queued.
* Garbage collection of unix sockets starts by selecting a set of
* candidate sockets which have reference only from being in flight
* (total_refs == inflight_refs). This condition is checked once during
* the candidate collection phase, and candidates are marked as such, so
* that non-candidates can later be ignored. While inflight_refs is
* protected by unix_gc_lock, total_refs (file count) is not, hence this
* is an instantaneous decision.
*
* Once a candidate, however, the socket must not be reinstalled into a
* file descriptor while the garbage collection is in progress.
*
* If the above conditions are met, then the directed graph of
* candidates (*) does not change while unix_gc_lock is held.
*
* Any operations that changes the file count through file descriptors
* (dup, close, sendmsg) does not change the graph since candidates are
* not installed in fds.
*
* Dequeing a candidate via recvmsg would install it into an fd, but
* that takes unix_gc_lock to decrement the inflight count, so it's
* serialized with garbage collection.
*
* MSG_PEEK is special in that it does not change the inflight count,
* yet does install the socket into an fd. The following lock/unlock
* pair is to ensure serialization with garbage collection. It must be
* done between incrementing the file count and installing the file into
* an fd.
*
* If garbage collection starts after the barrier provided by the
* lock/unlock, then it will see the elevated refcount and not mark this
* as a candidate. If a garbage collection is already in progress
* before the file count was incremented, then the lock/unlock pair will
* ensure that garbage collection is finished before progressing to
* installing the fd.
*
* (*) A -> B where B is on the queue of A or B is on the queue of C
* which is on the queue of listening socket A.
*/
UNIXCB(skb).fp = scm_fp_dup(scm->fp);
if (!UNIXCB(skb).fp)
return -ENOMEM;

for (i = scm->fp->count - 1; i >= 0; i--)
unix_inflight(scm->fp->user, scm->fp->fp[i]);
return 0;
spin_lock(&unix_gc_lock);
spin_unlock(&unix_gc_lock);
}

static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
Expand Down Expand Up @@ -2204,7 +2192,7 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
sk_peek_offset_fwd(sk, size);

if (UNIXCB(skb).fp)
scm.fp = scm_fp_dup(UNIXCB(skb).fp);
unix_peek_fds(&scm, skb);
}
err = (flags & MSG_TRUNC) ? skb->len - skip : size;

Expand Down Expand Up @@ -2445,7 +2433,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
/* It is questionable, see note in unix_dgram_recvmsg.
*/
if (UNIXCB(skb).fp)
scm.fp = scm_fp_dup(UNIXCB(skb).fp);
unix_peek_fds(&scm, skb);

sk_peek_offset_fwd(sk, chunk);

Expand Down
Loading

0 comments on commit 5a06261

Please sign in to comment.