Project

General

Profile

How to send patches to kernel » History » Revision 12

Revision 11 (Alexey Khoroshilov, 07/14/2022 04:24 PM) → Revision 12/13 (Alexey Khoroshilov, 08/16/2022 10:39 AM)

{{toc}} 

 h1. Сообщение об ошибке в виде патча 

 Ниже на примере рассматривается подготовка и отправка в kernel.org почтовой версии набора коммитов (патча) с исправлением ошибки, найденной в в коде драйвера при помощи Svace. Более полную информацию о разработке, подготовке и отправке патчей, в том числе для случаев изменений в коде драйверов и связанном с    платформами конечных устройств, а также о требованиях к отправляемому коду, можно получить в документации на "docs.kernel.org":https://docs.kernel.org/ ("Submitting patches: the essential guide to getting your code into the kernel":https://docs.kernel.org/process/submitting-patches.html, "Linux Kernel patch submission checklist":https://docs.kernel.org/process/submit-checklist.html, "A guide to the Kernel Development Process":https://docs.kernel.org/process/development-process.html). 

 h2. Предварительная настройка git 


 Для корректного оформления патчей все коммиты должны быть подписаны при помощи опции --signoff команды git commit. Для этого необходимо добавить в конфигурацию Git ваше имя и электронную почту в параметры значения параметров user.name и user.email, например: user.email: 

  git config --global user.name "Alexey Khoroshilov" 
 git config --global user.email "khoroshilov@ispras.ru" 

 Чтобы патчи, подготовленные для отправки в списки рассылки, не вставлять вручную в почтовый клиент,    можно использовать команду "git send-email":https://git-scm.com/docs/git-send-email. Для этого в конфигурацию Git в раздел [sendemail] необходимо добавить параметры, соответствующие настройкам сервера SMTP, через который будет отправляться почта. Часто достаточно задать адрес сервера SMTP, порт и тип шифрования: 

  git config --global sendemail.smtpServer "mail.ispras.ru" 
 git config --global sendemail.smtpServerPort "587" 
 git config --global sendemail.smtpEncryption "tls" 
 git config --global sendemail.smtpUser "ВАША ПОЧТА" 

 Также для изменения конфигурации Git можно использовать команду git config --global --edit, которая открывает файл конфигурации Git в редакторе.   

 Конфигурация Git для рассматриваемого примера выглядит следующим образом: 

  cat ~/.gitconfig  
 [user] 
       name = Alexey Khoroshilov 
       email = khoroshilov@ispras.ru 
 [sendemail] 
       smtpserver = mail.ispras.ru 
       smtpEncryption = tls 
       smtpserverport = 587 
       smtpuser = ВАША ПОЧТА 

 h2. Обновление репозитория до самой свежей версии и создание новой ветки. ветки 

 Перед внесением изменений в код ядра необходимо склонировать или обновить соответствующий репозиторий ядра и создать новую ветку для подготовки патча. 

 Как правило, клонируется или обновляется основной репозиторий ядра:  

  git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 

 или, если репозиторий был уже склонирован ранее 

  git pull 

 Создаем отдельную ветку для подготовки исправления (в рассматриваемом примере ветка названа по имени драйвера): 

  git checkout -b usb_gadget master 

 h2. Вносим необходимые исправления в код, соблюдая принятые правила форматирования 

 При внесении изменений в код необходимо соблюдать принятые в сообществе разработчиков ядра Linux правила форматирования кода (см. "Linux kernel coding style":https://docs.kernel.org/process/coding-style.html,  
 "root/Documentation/process/coding-style.rst":https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/coding-style.rst).   

 h2. Проверяем компилируемость ядра 

 После внесения изменений в код запускаем сборку ядра, по завершении которой необходимо проверить, что измененные файлы были скомпилированы: 

  make allmodconfig 
 make prepare 
 make modules_prepare 
 make M=drivers/xxx/    #или 
 make drivers/xxx/filename.o 

 h2. Проверяем отсутствие ошибок после исправления 

 **TODO:** Предоставить возможность прогнать SVACE на версии с применённым патчем. 

 

 h2. Коммитим исправления 

 Делаем коммит.    Используем --signoff, чтобы добавить    строчку "Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>"    (обязательно нужна). 

  git commit --signoff drivers/usb/gadget/inode.c 

 В теле коммита, для простоты, можно сразу писать багрепорт.    Шаблон такой: 

 <pre> 
 usb-gadget: Add module_put on error path in if_open() 

 If something happens (describe the path), then module_put is not  
 called (describe the problem). 
    
 Make if_open() do module_put on error path (describe the solution in imperative mood). 
 If the solution is trivial, this section can be omitted. 
    
 Found by Linux Verification Center (linuxtesting.org) with SVACE. 
 </pre> 

 Если ошибка найдена не при помощи SVACE, то это необходимо отразить в последней строчке, например: 
 Found by Linux Verification Center (linuxtesting.org) with syzkaller. 

 Рекомендуется познакомиться с "общими правилами оформления сообщений коммитов":https://chris.beams.io/posts/git-commit/, которые применимы в том числе и для коммитов в ядро Linux. 

 Вместо usb-gadget нужен определённый идентифицирующий префикс; его можно посмотреть в логе изменений конкретного файла. 

 При совместной разработке патча в конце коммита желательно указать участвующих коллег: 

 <pre> 
 Co-developed-by: Co-Author <coauthor@ispras.ru> 
 Signed-off-by: Co-Author <coauthor@ispras.ru> 
 </pre> 

 *Hint.* Если известен коммит, в котором была внесена исправляемая ошибка, то в текст коммита (перед строчкой "Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>") рекомендуется вставить строчку с префиксом "Fixes:". Её можно сгенерировать при помощи команды: 

 <pre> 
  git show -s --pretty="format:Fixes: %h (\"%s\")" HASH-OF-COMMIT-THAT-INTRODUCED-BUG 
 </pre> 

 В последнее время разработчики достаточно регулярно просят указать данный тег, поэтому рекомедуется делать это в обязательном порядке, даже если при этом приходится ссылаться на первоначальный коммит, который добавил соответствующий драйвер в ядро, т.е. ошибка была в коде изначально. 

 При поиске коммита, который внёс ошибку важно учитывать перемещения файла между директориями. Для этого бывает удобно воспользоваться опцией --follow, которая позволяет увидеть историю изменений в файле с учётом его перемещений внутри репозитория: 

 <pre> 
  git log -p --follow drivers/usb/gadget/legacy/inode.c 
 </pre> 


 


 h2. Создаем сам патч 

  git format-patch master..usb_gadget 

 Гит сделает что-то типа письма из того коммита, который был сделан ранее. 

 *Hint.* Имя текущей ветки можно и опустить: 

 <pre> 
  git format-patch master.. 
 </pre> 

 *Hint.* При генерации второй и последующих версий используйте аргумент -v: 

 <pre> 
  git format-patch -v 2 master.. 
 </pre> 


 h2. Проверяем его форматирование 

  ./scripts/checkpatch.pl 0001-xxx.patch 

 h2. Редактируем файл с патчем 

 h3. Тема письма 

 Если всё сделали правильно, то формат-патч сам создаст такую тему: 

  [PATCH] prefix: short description 

 

 h3. Идентифицируем адресатов 

  ./scripts/get_maintainer.pl 0001-xxx.patch 

 Удаляем то, что в скобочках круглых, ставим первому адресату To:, а остальным — Cc:.    Дописываем в письмо. Также добавляем в Cc список рассылки: ldv-project@linuxtesting.org. 

 На этом этапе в текст письма можно внести произвольные изменения. 

 В результате получается что-то типа: 

 <pre> 
 From 9bbb34d71038fc7015917646a3365bca20cacb02 Mon Sep 17 00:00:00 2001 
 From: Alexey Khoroshilov <khoroshilov@ispras.ru> 
 To: Mauro Carvalho Chehab <mchehab@infradead.org> 
 Cc: linux-media@vger.kernel.org 
 Cc: linux-kernel@vger.kernel.org 
 Cc: ldv-project@linuxtesting.org 
 Date: Thu, 26 May 2011 00:38:12 +0400 
 Subject: [PATCH] usb-gadget: unlock data->lock mutex on error path in ep_write() 

 ep_read() acquires data->lock mutex in get_ready_ep() and releases it on 
 all paths except for one: when usb_endpoint_xfer_isoc() failed. The 
 patch adds mutex_unlock(&data->lock) at that path. 

 Found by Linux Verification Center (linuxtesting.org) with SVACE. 

 Fixes: 193ab2a60700 ("usb: gadget: allow multiple gadgets to be built") 
 Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> 
 --- 
  drivers/usb/gadget/inode.c |      4 +++- 
  1 files changed, 3 insertions(+), 1 deletions(-) 

 diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c 
 index 3ed73f4..a01383f 100644 
 --- a/drivers/usb/gadget/inode.c 
 +++ b/drivers/usb/gadget/inode.c 
 @@ -386,8 +386,10 @@ ep_read (struct file *fd, char __user *buf, size_tlen, loff_t *ptr) 

	 /* halt any endpoint by doing a "wrong direction" i/o call */ 
	 if (usb_endpoint_dir_in(&data->desc)) { 
 - 		 if (usb_endpoint_xfer_isoc(&data->desc)) 
 + 		 if (usb_endpoint_xfer_isoc(&data->desc)) { 
 + 			 mutex_unlock(&data->lock); 
			 return -EINVAL; 
 + 		 } 
		 DBG (data->dev, "%s halt\n", data->name); 
		 spin_lock_irq (&data->dev->lock); 
		 if (likely (data->ep != NULL)) 
 -- 1.7.0.4 
 </pre> 

 

 h3. Внимательно проверяем орфографию 

 Например, можно скопировать текст из 0001-xxx.patch в какой-нибудь редактор документов, в котором включены соответствующие проверки. Это позволит не нервировать разработчиков орфографическими ошибками, а также избежать повторной отправки патчей. 

 

 h2. Отправляем 

  git send-email 0001-xxx.patch 

 Можно указать несколько патчей сразу через пробел, но если это независимые патчи, то делать этого **не нужно**, ибо тогда git скомпонует из них одну цепочку (письма будут ответами на первое). Конечно, если вы посылаете серию патчей, то это делается одной командой: 

  git send-email 0001-xxx.patch 0002-yyy.patch 0003-zzz.patch 

 Команда git send-email спрашивает кому отправить письма и т.д. Если в теле патча всё указано верно, то можно смело нажимать Enter ничего не вводя и git воспользуется значениями указанными в теле патча. 

 

 h1. Сообщение об ошибке без патча 

 Если вкратце, то готовим такое же письмо как и выше, и посылаем его тем же адресатам (см. ./scripts/get_maintainer.pl -f path_to_file), но только с описанием проблемы и её последствий, без предложения по исправлению. Посылаем из любого почтового клиента **плоским текстом (не HTML)**. 

 В конце письма необходимо вставить строчку: 

  Found by Linux Verification Center (linuxtesting.org) with SVACE. 


 h1. Перенос патчей в стабильную ветку ядра 

 h2. 1. Подготовка репозитория 

 Клонируем репозиторий со стабильными версиями ядра: 

  git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 
 cd linux-stable 

 Для перехода на ветку, в которою переносим патч, выполните команду: 

  git checkout linux-5.10.y 

 Создайте отдельную ветку для подготовки исправления (в рассматриваемом примере ветка названа по имени драйвера): 

  git checkout -b ath9k linux-5.10.y 

 h2. 2. Внесение необходимых изменений в код 

 Предполагается, что мы знаем хэш коммита, который необходимо перенести. Посмотрим, могут ли изменения, внесенные коммитом, чисто примениться к стабильной ветке: 

  git cherry-pick HASH-OF-COMMIT-THAT-NEEDS-TO-BE-BACKPORTED   

 Смотрим на вывод команды - существует несколько вариантов: 

 * Патч чисто применен. Отлично! Успешный @git cherry-pick@ автоматически применяет коммит к текущей ветке (что можно увидеть с помощью @git log@). 

 * Во время применения изменений произошел конфликт (CONFLICT). Это значит, что нам нужно вручную попытаться адаптировать изменения, внесенные коммитом, к коду стабильной ветки. Открываем файл, в котором произошел конфликт, находим конфликтное место и, по возможности, разрешаем конфликт. Важно осознавать, не привнесут ли ручные изменения новых багов и не нарушат ли логику кода. После коммитим свои исправления: 
 <pre> 
  git add FILE_WITH_CONFLICT 
  git commit -m "Fixed conflict in [FILE_WITH_CONFLICT]" 
 </pre> 
  Иногда бывает, что менее трудоемким и более безопасным путем будет откат к изначальному состоянию: 
 <pre> 
  git cherry-pick --abort 
 </pre> 

 Возможно выяснится, что предварительно необходимо перенести ряд других коммитов и после этого вернуться к переносу или адаптации целевого коммита. 

 Рекомендуется ознакомиться с документацией: @man git-cherry-pick@, либо https://git-scm.com/docs/git-cherry-pick.  

 После того как все необходимые изменения внесены, необходимо проверить компилируемость ядра и отсутствие ошибок после исправления - см. выше раздел про внесение патчей в основную ветку ядра. 

 h2. 3. Создание патча (серии патчей) 

  git format-patch linux-5.10.y..ath9k 

 Эта команда сгенерирует заготовку письма из того коммита, который мы перенесли. 

 *Hint.* Имя текущей ветки можно и опустить: 

 <pre> 
  git format-patch linux-5.10.y.. 
 </pre> 

 *Hint.* При генерации второй и последующих версий используйте аргумент -v: 

 <pre> 
  git format-patch -v 2 linux-5.10.y.. 
 </pre> 

 h2. 4. Редактирование файла с патчем 

 Строку @From: Автор оригинального коммита@ следует поместить в само письмо (т. е. поместить ниже заголовка письма и отделить одной строкой). 

 В заголовке правим отправителя и дату: 
 
  From: ВАШИ ИМЯ И ФАМИЛИЯ <ПОЧТА> 
 Date: <АКТУАЛЬНАЯ ДАТА> 


 В теме письма Subject *указываем [PATCH 5.10 1/1]*. При переносе патчей используется письмо с номером 0 (сопроводительное письмо для обоснования необходимости переноса), поэтому всегда посылаем серией. Если бэкпортируемых патчей два и более, то заключаем их в серию патчей. Например, если патчей два, то в первом письме указываем [PATCH 5.10 1/2], во втором соответственно [PATCH 5.10 2/2].  


 Через строку после @From: Автор оригинального коммита@ пишем, *не сокращая* хэш коммита: 

  commit HASH-OF-COMMIT-THAT-NEEDS-TO-BE-BACKPORTED upstream. 

 *Обязательно подписываем патч*: 
 <pre> 
 Signed-off-by: ВАШИ ИМЯ И ФАМИЛИЯ <ПОЧТА> 
 </pre> 

 Текст описания оригинального патча оставляем как есть.  

 Если нами были внесены какие-либо адаптивные изменения, их стоит описать после текста оригинального патча, до строк с подписями. 

 *Основными адресатами* являются: stable@vger.kernel.org и Greg Kroah-Hartman <gregkh@linuxfoundation.org>. 
 Остальных адресатов, которым отправим копии, идентифицируем с помощью скрипта. В конце добавляем: 
 <pre> 
  Cc: ldv-project@linuxtesting.org 
 </pre> 
 В результате получится примерно следующее: 

 <pre> 
 From 63845fa0bdcd3ea538c4f1e5d298a3b0e343fe20 Mon Sep 17 00:00:00 2001 
 From: ВАШИ ИМЯ И ФАМИЛИЯ <ПОЧТА> 
 To: stable@vger.kernel.org 
 To: Greg Kroah-Hartman <gregkh@linuxfoundation.org> 
 Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> 
 Cc: Kalle Valo <quic_kvalo@quicinc.com> 
 Cc: Alexey Khoroshilov <khoroshilov@ispras.ru> 
 Cc: ldv-project@linuxtesting.org 
 Date: Fri, 12 Aug 2022 22:06:23 +0900 
 Subject: [PATCH 5.10 1/1] ath9k_htc: fix NULL pointer dereference at ath9k_htc_rxep() 

 From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> 

 commit b0ec7e55fce65f125bd1d7f02e2dc4de62abee34 upstream. 

 syzbot is reporting lockdep warning followed by kernel panic at 
 ath9k_htc_rxep() [1], for ath9k_htc_rxep() depends on ath9k_rx_init() 
 being already completed. 

 Since ath9k_htc_rxep() is set by ath9k_htc_connect_svc(WMI_BEACON_SVC) 
 from ath9k_init_htc_services(), it is possible that ath9k_htc_rxep() is 
 called via timer interrupt before ath9k_rx_init() from ath9k_init_device() 
 is called. 

 Since we can't call ath9k_init_device() before ath9k_init_htc_services(), 
 let's hold ath9k_htc_rxep() no-op until ath9k_rx_init() completes. 

 Link: https://syzkaller.appspot.com/bug?extid=4d2d56175b934b9a7bf9 [1] 
 Reported-by: syzbot <syzbot+4d2d56175b934b9a7bf9@syzkaller.appspotmail.com> 
 Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> 
 Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> 
 Signed-off-by: ВАШИ ИМЯ И ФАМИЛИЯ <ПОЧТА> 
 --- 
  drivers/net/wireless/ath/ath9k/htc.h            | 1 + 
  drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 ++++++++ 
  2 files changed, 9 insertions(+) 

 diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h 
 index 0a1634238e67..4f71e962279a 100644 
 --- a/drivers/net/wireless/ath/ath9k/htc.h 
 +++ b/drivers/net/wireless/ath/ath9k/htc.h 
 @@ -281,6 +281,7 @@ struct ath9k_htc_rxbuf { 
  struct ath9k_htc_rx { 
 	 struct list_head rxbuf; 
 	 spinlock_t rxbuflock; 
 + 	 bool initialized; 
  }; 
 
  #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ 
 diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 
 index 30ddf333e04d..592034ea4b68 100644 
 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 
 +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 
 @@ -1133,6 +1133,10 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, 
 	 struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; 
 	 unsigned long flags; 
 
 + 	 /* Check if ath9k_rx_init() completed. */ 
 + 	 if (!data_race(priv->rx.initialized)) 
 + 		 goto err; 
 + 
 	 spin_lock_irqsave(&priv->rx.rxbuflock, flags); 
 	 list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { 
 		 if (!tmp_buf->in_process) { 
 @@ -1188,6 +1192,10 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv) 
 		 list_add_tail(&rxbuf->list, &priv->rx.rxbuf); 
 	 } 
 
 + 	 /* Allow ath9k_htc_rxep() to operate. */ 
 + 	 smp_wmb(); 
 + 	 priv->rx.initialized = true; 
 + 
 	 return 0; 
 
  err: 
 --  
 2.25.1 
 </pre> 

 h2. 5. Сопроводительное письмо 

 Также следует включить письмо с кратким описанием того, почему мы бэкпортируем коммит. 
 Письмо нужно включить в отправляемую серию патчей *под номером 0*. 

 Примерный вид письма: 
 <pre> 
 From: ВАШИ ИМЯ И ФАМИЛИЯ <ПОЧТА> 
 To: stable@vger.kernel.org 
 To: Greg Kroah-Hartman <gregkh@linuxfoundation.org> 
 Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> 
 Cc: Kalle Valo <quic_kvalo@quicinc.com> 
 Cc: Alexey Khoroshilov <khoroshilov@ispras.ru> 
 Cc: ldv-project@linuxtesting.org 
 Date: Mon, 1 Aug 2022 18:40:23 -0300 
 Subject: [PATCH 5.10 0/1] ath9k_htc: fix NULL pointer dereference at ath9k_htc_rxep() 

 Syzkaller reports NULL pointer dereference issue at ath9k_htc_rxep() 
 in 5.10 stable releases. The problem has been fixed by the following 
 patch which can be cleanly applied to the 5.10 branch. 

 Found by Linux Verification Center (linuxtesting.org) with Syzkaller. 
 </pre> 

 h2. 6. Отправка патчей 

 Как обычно используем команду git send-email: 

  git send-email 0000-xxx.patch 0001-yyy.patch 0002-zzz.patch 0003-xyz.patch