Unverified Commit 3d927574 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!12310 fix CVE-2024-40965

Merge Pull Request from: @ci-robot 
 
PR sync from: dinglongwei <dinglongwei1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/AE3NNTJJXYEBCZLDRJ224RTS26OWCC32/ 
fix CVE-2024-40965

Alexander Stein (1):
  i2c: lpi2c: Avoid calling clk_get_rate during transfer

Carlos Song (1):
  i2c: imx-lpi2c: return -EINVAL when i2c peripheral clk doesn't work

Peng Fan (1):
  i2c: imx-lpi2c: use bulk clk API

Uwe Kleine-König (2):
  clk: Add a devm variant of clk_rate_exclusive_get()
  clk: Provide !COMMON_CLK dummy for devm_clk_rate_exclusive_get()


-- 
2.17.1
 
https://gitee.com/src-openeuler/kernel/issues/IACTBX 
 
Link:https://gitee.com/openeuler/kernel/pulls/12310

 

Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents c5a7d44f f3a56719
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -920,6 +920,25 @@ int clk_rate_exclusive_get(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_rate_exclusive_get);

static void devm_clk_rate_exclusive_put(void *data)
{
	struct clk *clk = data;

	clk_rate_exclusive_put(clk);
}

int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk)
{
	int ret;

	ret = clk_rate_exclusive_get(clk);
	if (ret)
		return ret;

	return devm_add_action_or_reset(dev, devm_clk_rate_exclusive_put, clk);
}
EXPORT_SYMBOL_GPL(devm_clk_rate_exclusive_get);

static void clk_core_unprepare(struct clk_core *core)
{
	lockdep_assert_held(&prepare_lock);
+28 −12
Original line number Diff line number Diff line
@@ -94,11 +94,13 @@ enum lpi2c_imx_pincfg {

struct lpi2c_imx_struct {
	struct i2c_adapter	adapter;
	struct clk		*clk;
	int			num_clks;
	struct clk_bulk_data	*clks;
	void __iomem		*base;
	__u8			*rx_buf;
	__u8			*tx_buf;
	struct completion	complete;
	unsigned long		rate_per;
	unsigned int		msglen;
	unsigned int		delivered;
	unsigned int		block_data;
@@ -207,7 +209,8 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)

	lpi2c_imx_set_mode(lpi2c_imx);

	clk_rate = clk_get_rate(lpi2c_imx->clk);
	clk_rate = lpi2c_imx->rate_per;

	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
		filt = 0;
	else
@@ -567,11 +570,12 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
	strlcpy(lpi2c_imx->adapter.name, pdev->name,
		sizeof(lpi2c_imx->adapter.name));

	lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(lpi2c_imx->clk)) {
		dev_err(&pdev->dev, "can't get I2C peripheral clock\n");
		return PTR_ERR(lpi2c_imx->clk);
	ret = devm_clk_bulk_get_all(&pdev->dev, &lpi2c_imx->clks);
	if (ret < 0) {
		dev_err(&pdev->dev, "can't get I2C peripheral clock, ret=%d\n", ret);
		return ret;
	}
	lpi2c_imx->num_clks = ret;

	ret = of_property_read_u32(pdev->dev.of_node,
				   "clock-frequency", &lpi2c_imx->bitrate);
@@ -588,11 +592,23 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
	i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
	platform_set_drvdata(pdev, lpi2c_imx);

	ret = clk_prepare_enable(lpi2c_imx->clk);
	if (ret) {
		dev_err(&pdev->dev, "clk enable failed %d\n", ret);
	ret = clk_bulk_prepare_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
	if (ret)
		return ret;
	}

	/*
	 * Lock the parent clock rate to avoid getting parent clock upon
	 * each transfer
	 */
	ret = devm_clk_rate_exclusive_get(&pdev->dev, lpi2c_imx->clks[0].clk);
	if (ret)
		return dev_err_probe(&pdev->dev, ret,
				     "can't lock I2C peripheral clock rate\n");

	lpi2c_imx->rate_per = clk_get_rate(lpi2c_imx->clks[0].clk);
	if (!lpi2c_imx->rate_per)
		return dev_err_probe(&pdev->dev, -EINVAL,
				     "can't get I2C peripheral clock rate\n");

	pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
	pm_runtime_use_autosuspend(&pdev->dev);
@@ -639,7 +655,7 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
{
	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);

	clk_disable_unprepare(lpi2c_imx->clk);
	clk_bulk_disable_unprepare(lpi2c_imx->num_clks, lpi2c_imx->clks);
	pinctrl_pm_select_sleep_state(dev);

	return 0;
@@ -651,7 +667,7 @@ static int __maybe_unused lpi2c_runtime_resume(struct device *dev)
	int ret;

	pinctrl_pm_select_default_state(dev);
	ret = clk_prepare_enable(lpi2c_imx->clk);
	ret = clk_bulk_prepare_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
	if (ret) {
		dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
		return ret;
+17 −0
Original line number Diff line number Diff line
@@ -190,6 +190,18 @@ bool clk_is_match(const struct clk *p, const struct clk *q);
 */
int clk_rate_exclusive_get(struct clk *clk);

/**
 * devm_clk_rate_exclusive_get - devm variant of clk_rate_exclusive_get
 * @dev: device the exclusivity is bound to
 * @clk: clock source
 *
 * Calls clk_rate_exclusive_get() on @clk and registers a devm cleanup handler
 * on @dev to call clk_rate_exclusive_put().
 *
 * Must not be called from within atomic context.
 */
int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk);

/**
 * clk_rate_exclusive_put - release exclusivity over the rate control of a
 *                          producer
@@ -256,6 +268,11 @@ static inline int clk_rate_exclusive_get(struct clk *clk)
	return 0;
}

static inline int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk)
{
	return 0;
}

static inline void clk_rate_exclusive_put(struct clk *clk) {}

#endif