lkml.org 
[lkml]   [2021]   [May]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.12 18/79] usb: gadget: f_uac1: validate input parameters
    Date
    From: Ruslan Bilovol <ruslan.bilovol@gmail.com>

    [ Upstream commit a59c68a6a3d1b18e2494f526eb19893a34fa6ec6 ]

    Currently user can configure UAC1 function with
    parameters that violate UAC1 spec or are not supported
    by UAC1 gadget implementation.

    This can lead to incorrect behavior if such gadget
    is connected to the host - like enumeration failure
    or other issues depending on host's UAC1 driver
    implementation, bringing user to a long hours
    of debugging the issue.

    Instead of silently accept these parameters, throw
    an error if they are not valid.

    Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com>
    Link: https://lore.kernel.org/r/1614599375-8803-5-git-send-email-ruslan.bilovol@gmail.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/usb/gadget/function/f_uac1.c | 43 ++++++++++++++++++++++++++++
    1 file changed, 43 insertions(+)

    diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
    index 560382e0a8f3..e65f474ad7b3 100644
    --- a/drivers/usb/gadget/function/f_uac1.c
    +++ b/drivers/usb/gadget/function/f_uac1.c
    @@ -19,6 +19,9 @@
    #include "u_audio.h"
    #include "u_uac1.h"

    +/* UAC1 spec: 3.7.2.3 Audio Channel Cluster Format */
    +#define UAC1_CHANNEL_MASK 0x0FFF
    +
    struct f_uac1 {
    struct g_audio g_audio;
    u8 ac_intf, as_in_intf, as_out_intf;
    @@ -30,6 +33,11 @@ static inline struct f_uac1 *func_to_uac1(struct usb_function *f)
    return container_of(f, struct f_uac1, g_audio.func);
    }

    +static inline struct f_uac1_opts *g_audio_to_uac1_opts(struct g_audio *audio)
    +{
    + return container_of(audio->func.fi, struct f_uac1_opts, func_inst);
    +}
    +
    /*
    * DESCRIPTORS ... most are static, but strings and full
    * configuration descriptors are built on demand.
    @@ -505,11 +513,42 @@ static void f_audio_disable(struct usb_function *f)

    /*-------------------------------------------------------------------------*/

    +static int f_audio_validate_opts(struct g_audio *audio, struct device *dev)
    +{
    + struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
    +
    + if (!opts->p_chmask && !opts->c_chmask) {
    + dev_err(dev, "Error: no playback and capture channels\n");
    + return -EINVAL;
    + } else if (opts->p_chmask & ~UAC1_CHANNEL_MASK) {
    + dev_err(dev, "Error: unsupported playback channels mask\n");
    + return -EINVAL;
    + } else if (opts->c_chmask & ~UAC1_CHANNEL_MASK) {
    + dev_err(dev, "Error: unsupported capture channels mask\n");
    + return -EINVAL;
    + } else if ((opts->p_ssize < 1) || (opts->p_ssize > 4)) {
    + dev_err(dev, "Error: incorrect playback sample size\n");
    + return -EINVAL;
    + } else if ((opts->c_ssize < 1) || (opts->c_ssize > 4)) {
    + dev_err(dev, "Error: incorrect capture sample size\n");
    + return -EINVAL;
    + } else if (!opts->p_srate) {
    + dev_err(dev, "Error: incorrect playback sampling rate\n");
    + return -EINVAL;
    + } else if (!opts->c_srate) {
    + dev_err(dev, "Error: incorrect capture sampling rate\n");
    + return -EINVAL;
    + }
    +
    + return 0;
    +}
    +
    /* audio function driver setup/binding */
    static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
    {
    struct usb_composite_dev *cdev = c->cdev;
    struct usb_gadget *gadget = cdev->gadget;
    + struct device *dev = &gadget->dev;
    struct f_uac1 *uac1 = func_to_uac1(f);
    struct g_audio *audio = func_to_g_audio(f);
    struct f_uac1_opts *audio_opts;
    @@ -519,6 +558,10 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
    int rate;
    int status;

    + status = f_audio_validate_opts(audio, dev);
    + if (status)
    + return status;
    +
    audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst);

    us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
    --
    2.30.2
    \
     
     \ /
      Last update: 2021-05-02 16:04    [W:5.786 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site