From e8ce387b9e7a909d0475e8bb1168589c63f03d71 Mon Sep 17 00:00:00 2001 From: Fede2782 <78815152+Fede2782@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:03:11 +0200 Subject: [PATCH] exynos9611: import P615XXS8FXE4 (#4) --- arch/arm64/boot/dts/Makefile | 6 +- .../arm/bv_r38p1/mali_kbase_kinstr_prfcnt.c | 5 + drivers/usb/notify/dock_notify.c | 7 +- drivers/usb/notify/usb_notify.c | 279 +++++++++++++++++- drivers/usb/notify/usb_notify_sysfs.c | 54 ++++ drivers/usb/notify/usb_notify_sysfs.h | 2 + include/linux/usb_hw_param.h | 2 + include/linux/usb_notify.h | 21 ++ security/sdp/fs_handler.c | 7 +- security/sdp/pub_crypto_emul.c | 13 +- 10 files changed, 381 insertions(+), 15 deletions(-) diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index b3731b6c0018..2f16c117e6a3 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 -dtbo-y += samsung/exynos9611-gta4xl_eur_open_03.dtbo dtbo-y += samsung/exynos9611-gta4xl_eur_open_01.dtbo -dtbo-y += samsung/exynos9611-gta4xl_eur_open_04.dtbo +dtbo-y += samsung/exynos9611-gta4xl_eur_open_08.dtbo dtbo-y += samsung/exynos9611-gta4xl_eur_open_05.dtbo dtbo-y += samsung/exynos9611-gta4xl_eur_open_09.dtbo -dtbo-y += samsung/exynos9611-gta4xl_eur_open_08.dtbo +dtbo-y += samsung/exynos9611-gta4xl_eur_open_03.dtbo +dtbo-y += samsung/exynos9611-gta4xl_eur_open_04.dtbo dtb-y += exynos/exynos9610.dtb targets += dtbs diff --git a/drivers/gpu/arm/bv_r38p1/mali_kbase_kinstr_prfcnt.c b/drivers/gpu/arm/bv_r38p1/mali_kbase_kinstr_prfcnt.c index 4c99e6301893..a86ee8b780ce 100644 --- a/drivers/gpu/arm/bv_r38p1/mali_kbase_kinstr_prfcnt.c +++ b/drivers/gpu/arm/bv_r38p1/mali_kbase_kinstr_prfcnt.c @@ -1170,6 +1170,11 @@ void kbasep_kinstr_prfcnt_client_destroy(struct kbase_kinstr_prfcnt_client *cli) { if (!cli) return; + /* If virtualizer_client is already setup, the client is in working order. + * One needs to ensure there is no aync dump actions inflight. + */ + if (cli->hvcli) + flush_work(&cli->async.dump_work); kbase_hwcnt_virtualizer_client_destroy(cli->hvcli); kbasep_kinstr_prfcnt_sample_array_free(&cli->sample_arr); diff --git a/drivers/usb/notify/dock_notify.c b/drivers/usb/notify/dock_notify.c index 7a6af76ac4ee..df15e6a6cc1d 100644 --- a/drivers/usb/notify/dock_notify.c +++ b/drivers/usb/notify/dock_notify.c @@ -242,10 +242,13 @@ static int call_device_notify(struct usb_device *dev, int connect) #endif } #ifdef CONFIG_USB_NOTIFY_PROC_LOG - else + else { + send_otg_notify(o_notify, + NOTIFY_EVENT_DEVICE_CONNECT, 0); store_usblog_notify(NOTIFY_PORT_DISCONNECT, (void *)&dev->descriptor.idVendor, (void *)&dev->descriptor.idProduct); + } #endif } else { if (connect) @@ -429,6 +432,8 @@ static int dev_notify(struct notifier_block *self, #if defined(CONFIG_USB_HW_PARAM) set_hw_param(dev); #endif + check_usbaudio(dev); + check_usbgroup(dev); break; case USB_DEVICE_REMOVE: call_device_notify(dev, 0); diff --git a/drivers/usb/notify/usb_notify.c b/drivers/usb/notify/usb_notify.c index 8d7d0782524c..037899d3aa9e 100644 --- a/drivers/usb/notify/usb_notify.c +++ b/drivers/usb/notify/usb_notify.c @@ -28,6 +28,8 @@ #include "usb_notify_sysfs.h" #define DEFAULT_OVC_POLL_SEC 3 +#define MAX_SECURE_CONNECTION 10 +#define MAX_VAL 0x7FFFFFFF struct ovc { struct otg_notify *o_notify; @@ -97,6 +99,8 @@ struct usb_notify { int c_status; int sec_whitelist_enable; int reserve_vbus_booster; + int restricted; + unsigned int secure_connect_group[USB_GROUP_MAX]; #if defined(CONFIG_USB_HW_PARAM) unsigned long long hw_param[USB_CCIC_HW_PARAM_MAX]; #endif @@ -671,7 +675,7 @@ static void update_cable_status(struct otg_notify *n, unsigned long event, if (check_block_event(n, event) || (check_event_type(u_notify->c_type) & NOTIFY_EVENT_NEED_HOST && - n->unsupport_host)) + (n->unsupport_host || u_notify->restricted))) u_notify->c_status = (start) ? NOTIFY_EVENT_BLOCKING : NOTIFY_EVENT_BLOCKED; else @@ -903,6 +907,71 @@ int set_notify_disable(struct usb_notify_dev *udev, int disable) skip: return 0; } +static int set_notify_lock_state(struct usb_notify_dev *udev) +{ + struct otg_notify *n = udev->o_notify; + struct usb_notify *u_notify = (struct usb_notify *)(n->u_notify); + int i; + + if (udev->secure_lock) { + pr_info("%s lock\n", __func__); + } else { + for (i = 0; i < USB_GROUP_MAX; i++) + u_notify->secure_connect_group[i] = 0; + pr_info("%s unlock host cable=%d, restricted=%d\n", __func__, + is_host_cable_block(n), u_notify->restricted); + if (is_host_cable_block(n) && u_notify->restricted) { + u_notify->restricted = 0; + send_otg_notify(n, VIRT_EVENT(u_notify->c_type), 1); + } else + u_notify->restricted = 0; + } + + return 0; +} + +void send_usb_restrict_uevent(int usb_restrict) +{ + struct otg_notify *o_notify = get_otg_notify(); + char *envp[4]; + char *type = {"TYPE=usbrestrict"}; + char *state = {"STATE=ADD"}; + char *words; + int index = 0; + + if (!o_notify) { + pr_err("%s o_notify is null\n", __func__); + goto err; + } + + envp[index++] = type; + envp[index++] = state; + + switch (usb_restrict) { + case USB_SECURE_RESTRICTED: + words = "WORDS=securerestrict"; + break; + case USB_SECURE_RELEASE: + words = "WORDS=securerelease"; + break; + default: + pr_err("%s invalid input\n", __func__); + goto err; + } + + envp[index++] = words; + + envp[index++] = NULL; + + if (send_usb_notify_uevent(o_notify, envp)) { + pr_err("%s error\n", __func__); + goto err; + } + pr_info("%s: %s(%d)\n", __func__, words, usb_restrict); +err: + return; +} +EXPORT_SYMBOL(send_usb_restrict_uevent); void send_usb_err_uevent(int err_type, int mode) { @@ -1139,6 +1208,17 @@ static void otg_notify_state(struct otg_notify *n, event = PHY_EVENT(event); type = check_event_type(event); + + if (virtual && enable) { + if (check_event_type(event) & NOTIFY_EVENT_NEED_HOST) { + if (!(check_event_type(u_notify->c_type) + & NOTIFY_EVENT_NEED_HOST)) { + pr_err("event skip. mismatch cable type(%s)\n", + event_string(u_notify->c_type)); + goto no_save_event; + } + } + } if (!(type & NOTIFY_EVENT_NOSAVE)) { update_cable_status(n, event, virtual, enable, 1); @@ -1239,6 +1319,13 @@ static void otg_notify_state(struct otg_notify *n, pr_err("now host mode, skip this command\n"); goto err; } + + if (u_notify->restricted) { + send_usb_restrict_uevent(USB_SECURE_RESTRICTED); + pr_err("now restricted, skip this command\n"); + goto err; + } + u_notify->ndev.mode = NOTIFY_HOST_MODE; if (n->is_host_wakelock) wake_lock(&u_notify->wlock); @@ -1512,9 +1599,15 @@ static void extra_notify_state(struct otg_notify *n, (NOTIFY_EVENT_MMD_EXT_CURRENT, enable); break; case NOTIFY_EVENT_DEVICE_CONNECT: - if (!u_notify->is_device) { - u_notify->is_device = 1; - send_external_notify(EXTERNAL_NOTIFY_DEVICEADD, 1); + if (enable) { + if (!u_notify->is_device) { + u_notify->is_device = 1; + send_external_notify(EXTERNAL_NOTIFY_DEVICEADD, 1); + } + } + if (u_notify->udev.secure_lock) { + if (!enable) + detect_illegal_condition(NOTIFY_EVENT_SECURE_DISCONNECTION); } break; case NOTIFY_EVENT_GAMEPAD_CONNECT: @@ -1965,6 +2058,183 @@ bool is_blocked(struct otg_notify *n, int type) } EXPORT_SYMBOL(is_blocked); +#define MAX_C_D_L (2048) +int check_usbaudio(struct usb_device *dev) +{ + struct otg_notify *o_notify = get_otg_notify(); + struct usb_notify *u_notify = NULL; + struct usb_interface *intf; + struct usb_host_interface *alts; + unsigned int i; + int ret = 0; + u16 total_length; + + if (!o_notify) { + pr_err("%s o_notify is null\n", __func__); + goto done; + } + u_notify = (struct usb_notify *)(o_notify->u_notify); + + if (!u_notify) { + pr_err("%s u_notify structure is null\n", + __func__); + goto done; + } + + if (!u_notify->udev.secure_lock) + goto done; + + if (!dev->actconfig) { + pr_info("%s no set config\n", __func__); + goto done; + } + + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + intf = dev->actconfig->interface[i]; + alts = intf->cur_altsetting; + + if (alts->desc.bInterfaceClass == USB_CLASS_AUDIO) { + total_length = le16_to_cpu(dev->actconfig->desc.wTotalLength); + if (total_length > MAX_C_D_L) { + pr_info("%s total_length %u\n", __func__, total_length); + detect_illegal_condition(NOTIFY_EVENT_AUDIO_DESCRIPTOR); + ret = -EACCES; + break; + } + } + } +done: + return ret; +} +EXPORT_SYMBOL(check_usbaudio); + +int check_usbgroup(struct usb_device *dev) +{ + struct otg_notify *o_notify = get_otg_notify(); + struct usb_notify *u_notify = NULL; + struct usb_interface *intf; + struct usb_host_interface *alts; + struct usb_device *hdev; + unsigned int i; + int ret = 0; + bool is_audio_group = false; + + if (!o_notify) { + pr_err("%s o_notify is null\n", __func__); + goto done; + } + u_notify = (struct usb_notify *)(o_notify->u_notify); + + if (!u_notify) { + pr_err("%s u_notify structure is null\n", + __func__); + goto done; + } + + hdev = dev->parent; + if (!hdev) { + pr_err("%s root hub is not counted\n", + __func__); + goto done; + } + + if (!u_notify->udev.secure_lock) + goto done; + + if (!dev->actconfig) { + pr_info("%s no set config\n", __func__); + goto done; + } + + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + intf = dev->actconfig->interface[i]; + alts = intf->cur_altsetting; + + if (alts->desc.bInterfaceClass == USB_CLASS_AUDIO) { + is_audio_group = true; + break; + } + } + + if (is_audio_group) { + if (u_notify->secure_connect_group[USB_GROUP_AUDIO] < MAX_VAL) + u_notify->secure_connect_group[USB_GROUP_AUDIO]++; + } else { + if (u_notify->secure_connect_group[USB_GROUP_OTEHR] < MAX_VAL) + u_notify->secure_connect_group[USB_GROUP_OTEHR]++; + } + + pr_info("%s current audio_cnt=%d, other_cnt=%d\n", __func__, + u_notify->secure_connect_group[USB_GROUP_AUDIO], + u_notify->secure_connect_group[USB_GROUP_OTEHR]); + +done: + return ret; +} +EXPORT_SYMBOL(check_usbgroup); + +static int check_secure_connection(struct usb_notify *u_notify) +{ + int i; + + for (i = 0; i < USB_GROUP_MAX; i++) { + if (u_notify->secure_connect_group[i] >= MAX_SECURE_CONNECTION) + return true; + } + return false; +} + +int detect_illegal_condition(int type) +{ + struct otg_notify *o_notify = get_otg_notify(); + struct usb_notify *u_notify; + int ret = 0, restricted = 0; + + if (!o_notify) { + pr_err("%s otg_notify is null\n", __func__); + return ret; + } + + u_notify = (struct usb_notify *)(o_notify->u_notify); + if (!u_notify) { + pr_err("%s usb_notify is null\n", __func__); + return ret; + } + + pr_info("%s type %d +\n", __func__, type); + + switch (type) { + case NOTIFY_EVENT_AUDIO_DESCRIPTOR: + restricted = 1; +#if defined(CONFIG_USB_HW_PARAM) + if (o_notify) + inc_hw_param(o_notify, USB_HOST_OVER_AUDIO_DESCRIPTOR_COUNT); +#endif + break; + case NOTIFY_EVENT_SECURE_DISCONNECTION: + if (check_secure_connection(u_notify)) + restricted = 1; + break; + default: + break; + } + + if (restricted) { + u_notify->restricted = 1; +#if defined(CONFIG_USB_HW_PARAM) + if (o_notify) + inc_hw_param(o_notify, USB_HOST_SB_COUNT); +#endif + if (is_host_cable_enable(o_notify)) + send_otg_notify(o_notify, VIRT_EVENT(u_notify->c_type), 0); + } + + pr_info("%s type %d restricted=%d -\n", __func__, type, restricted); + + return ret; +} +EXPORT_SYMBOL(detect_illegal_condition); + bool is_snkdfp_usb_device_connected(struct otg_notify *n) { struct usb_notify *u_notify = NULL; @@ -2197,6 +2467,7 @@ int set_otg_notify(struct otg_notify *n) u_notify->udev.name = "usb_control"; u_notify->udev.set_disable = set_notify_disable; u_notify->udev.set_mdm = set_notify_mdm; + u_notify->udev.set_lock_state = set_notify_lock_state; u_notify->udev.o_notify = n; ret = usb_notify_dev_register(&u_notify->udev); diff --git a/drivers/usb/notify/usb_notify_sysfs.c b/drivers/usb/notify/usb_notify_sysfs.c index 7be41b665c81..d94145413ab2 100644 --- a/drivers/usb/notify/usb_notify_sysfs.c +++ b/drivers/usb/notify/usb_notify_sysfs.c @@ -74,6 +74,8 @@ usb_hw_param_print[USB_CCIC_HW_PARAM_MAX][MAX_HWPARAM_STRING] = { {"F_CNT"}, {"CC_KILLER"}, {"CC_FWERR"}, + {"H_SB"}, + {"H_OAD"}, {"C_ARP"}, {"CC_VER"}, }; @@ -768,6 +770,56 @@ int usb_notify_dev_uevent(struct usb_notify_dev *udev, char *envp_ext[]) } EXPORT_SYMBOL_GPL(usb_notify_dev_uevent); +static ssize_t usb_sl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_notify_dev *udev = (struct usb_notify_dev *) + dev_get_drvdata(dev); + + if (udev == NULL) { + pr_err("udev is NULL\n"); + return -EINVAL; + } + pr_info("%s secure_lock = %lu\n", + __func__, udev->secure_lock); + + return sprintf(buf, "%lu\n", udev->secure_lock); +} + +static ssize_t usb_sl_store( + struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) + +{ + struct usb_notify_dev *udev = (struct usb_notify_dev *) + dev_get_drvdata(dev); + unsigned long secure_lock = 0; + int sret = -EINVAL; + size_t ret = -ENOMEM; + + if (udev == NULL) { + pr_err("udev is NULL\n"); + return -EINVAL; + } + if (size > PAGE_SIZE) { + pr_err("%s size(%zu) is too long.\n", __func__, size); + goto error; + } + + sret = sscanf(buf, "%lu", &secure_lock); + if (sret != 1) + goto error; + + udev->secure_lock = secure_lock; + udev->set_lock_state(udev); + + pr_info("%s secure_lock = %lu\n", + __func__, udev->secure_lock); + ret = size; + +error: + return ret; +} static DEVICE_ATTR(disable, 0664, disable_show, disable_store); static DEVICE_ATTR(usb_data_enabled, 0664, usb_data_enabled_show, usb_data_enabled_store); @@ -780,6 +832,7 @@ static DEVICE_ATTR(whitelist_for_mdm, 0664, static DEVICE_ATTR(usb_hw_param, 0664, usb_hw_param_show, usb_hw_param_store); static DEVICE_ATTR(hw_param, 0664, hw_param_show, hw_param_store); #endif +static DEVICE_ATTR_RW(usb_sl); static struct attribute *usb_notify_attrs[] = { &dev_attr_disable.attr, @@ -792,6 +845,7 @@ static struct attribute *usb_notify_attrs[] = { &dev_attr_usb_hw_param.attr, &dev_attr_hw_param.attr, #endif + &dev_attr_usb_sl.attr, NULL, }; diff --git a/drivers/usb/notify/usb_notify_sysfs.h b/drivers/usb/notify/usb_notify_sysfs.h index e90fe76bd89d..a1ba0ab44ac5 100644 --- a/drivers/usb/notify/usb_notify_sysfs.h +++ b/drivers/usb/notify/usb_notify_sysfs.h @@ -43,9 +43,11 @@ struct usb_notify_dev { int index; unsigned long usb_data_enabled; unsigned long disable_state; + unsigned long secure_lock; char disable_state_cmd[MAX_DISABLE_STR_LEN]; int (*set_disable)(struct usb_notify_dev *, int); void (*set_mdm)(struct usb_notify_dev *udev, int mdm_disable); + int (*set_lock_state)(struct usb_notify_dev *udev); char whitelist_str[MAX_WHITELIST_STR_LEN]; int whitelist_array_for_mdm[MAX_CLASS_TYPE_NUM+1]; }; diff --git a/include/linux/usb_hw_param.h b/include/linux/usb_hw_param.h index 9f63dedc4813..60336b4fb56b 100644 --- a/include/linux/usb_hw_param.h +++ b/include/linux/usb_hw_param.h @@ -62,6 +62,8 @@ enum usb_hw_param { USB_HALL_FOLDING_COUNT, USB_CCIC_USB_KILLER_COUNT, USB_CCIC_FWUP_ERROR_COUNT, + USB_HOST_SB_COUNT, + USB_HOST_OVER_AUDIO_DESCRIPTOR_COUNT, USB_CLIENT_ANDROID_AUTO_RESET_POPUP_COUNT, USB_CCIC_VERSION, USB_CCIC_HW_PARAM_MAX, diff --git a/include/linux/usb_notify.h b/include/linux/usb_notify.h index f598326edb38..20ab35fb081c 100644 --- a/include/linux/usb_notify.h +++ b/include/linux/usb_notify.h @@ -121,10 +121,25 @@ enum otg_notify_data_role { HNOTIFY_DFP, }; +enum usb_restrict_type { + USB_SECURE_RESTRICTED, + USB_SECURE_RELEASE, +}; + +enum usb_restrict_group { + USB_GROUP_AUDIO, + USB_GROUP_OTEHR, + USB_GROUP_MAX, +}; enum usb_err_type { USB_ERR_ABNORMAL_RESET, }; +enum otg_notify_illegal_type { + NOTIFY_EVENT_AUDIO_DESCRIPTOR, + NOTIFY_EVENT_SECURE_DISCONNECTION, +}; + enum usb_current_state { NOTIFY_SUSPEND, NOTIFY_UNCONFIGURE, @@ -190,6 +205,9 @@ extern int usb_check_whitelist_for_mdm(struct usb_device *dev); extern int usb_otg_restart_accessory(struct usb_device *dev); extern int send_usb_notify_uevent (struct otg_notify *n, char *envp_ext[]); +extern int detect_illegal_condition(int type); +extern int check_usbaudio(struct usb_device *dev); +extern int check_usbgroup(struct usb_device *dev); #if defined(CONFIG_USB_HW_PARAM) extern unsigned long long *get_hw_param(struct otg_notify *n, enum usb_hw_param index); @@ -231,6 +249,9 @@ static inline int usb_otg_restart_accessory(struct usb_device *dev) {return 0; } static inline int send_usb_notify_uevent (struct otg_notify *n, char *envp_ext[]) {return 0; } +static inline int detect_illegal_condition(int type) {return 0; } +static inline int check_usbaudio(struct usb_device *dev) {return 0; } +static inline int check_usbgroup(struct usb_device *dev) {return 0; } #if defined(CONFIG_USB_HW_PARAM) static inline unsigned long long *get_hw_param(struct otg_notify *n, enum usb_hw_param index) {return NULL; } diff --git a/security/sdp/fs_handler.c b/security/sdp/fs_handler.c index 62dda8d95e68..486c6542225a 100644 --- a/security/sdp/fs_handler.c +++ b/security/sdp/fs_handler.c @@ -169,11 +169,15 @@ static int __recver(struct sk_buff *skb, struct nlmsghdr *nlh) result_t *result = (result_t *)data; sdp_fs_handler_request_t *req = NULL; + if (skb->len < (NLMSG_HDRLEN + sizeof(result_t))) { + SDP_FS_HANDLER_LOGE("crypto result :: length error!\n"); + break; + } + printk("result : req_id[%d], opcode[%d] ret[%d]\n", result->request_id, result->opcode, result->ret); spin_lock(&g_sdp_fs_handler_control.lock); req = request_find(&g_sdp_fs_handler_control, result->request_id); - spin_unlock(&g_sdp_fs_handler_control.lock); if(req == NULL) { SDP_FS_HANDLER_LOGE("crypto result :: error! can't find request %d\n", @@ -188,6 +192,7 @@ static int __recver(struct sk_buff *skb, struct nlmsghdr *nlh) memset(result, 0, sizeof(result_t)); request_free(req); } + spin_unlock(&g_sdp_fs_handler_control.lock); break; } default: diff --git a/security/sdp/pub_crypto_emul.c b/security/sdp/pub_crypto_emul.c index f7a7f164928a..b5e0cde600dc 100644 --- a/security/sdp/pub_crypto_emul.c +++ b/security/sdp/pub_crypto_emul.c @@ -213,8 +213,13 @@ static int pub_crypto_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) result_t *result = (result_t *)data; pub_crypto_request_t *req = NULL; - req = request_find(&g_pub_crypto_control, result->request_id); + if (skb->len < (NLMSG_HDRLEN + sizeof(result_t))) { + PUB_CRYPTO_LOGE("crypto_receive_msg: length error\n"); + break; + } + spin_lock(&g_pub_crypto_control.lock); + req = request_find(&g_pub_crypto_control, result->request_id); if(req) { memcpy(&req->result, result, sizeof(result_t)); req->state = PUB_CRYPTO_REQ_FINISHED; @@ -222,6 +227,7 @@ static int pub_crypto_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) memset(result, 0, sizeof(result_t)); } + spin_unlock(&g_pub_crypto_control.lock); break; } default: @@ -416,21 +422,16 @@ static pub_crypto_request_t *request_find(pub_crypto_control_t *con, u32 request_id) { struct list_head *entry; - spin_lock(&con->lock); - list_for_each(entry, &con->pending_list) { pub_crypto_request_t *req; req = list_entry(entry, pub_crypto_request_t, list); if (req->id == request_id) { req_dump(req, "found"); - spin_unlock(&con->lock); return req; } } - spin_unlock(&con->lock); - PUB_CRYPTO_LOGE("Can't find request %d\n", request_id); return NULL; }