stable kernelにコントリビュートする

この記事はLinux Advent Calendar 2021の18日目の記事です。

stable kernelへのコントリビュート

コントリビュートの方法としては次のような方法があると思います。

  • テストする

  • patchをレビューする

  • patchをバックポートする

  • その他

本記事ではpatchをバックポートする場合について書いてみたいと思います。基本的にはEverything you ever wanted to know about Linux -stable releases — The Linux Kernel documentationを読みましょうというところではありますが😑

patchをバックポートする理由

通常、mainlineに入ったバグ修正のpatchはstable treeに取り込まれますが、何かしらの理由で取り込まれていなかったり、patchが当たらずにエラーになったりして取り込まれないという場合があります。後者の場合は特にpatchの修正が必要になってきます。

patchをバックポートする

git-amを使ってpatchを当ててコンフリクトしたところを直してといった感じで通常通りに修正すればOKです。

stable kernel固有のお作法

バックポートしたpatchの先頭はこのような行が必要です。2行目のcommit hashの行は何パターンか書き方がある感じです。ここでは自分が書いてる書き方です。

From: <Author name><author email>

commit <commit hash>  upstream.

git-amでpatchを当てて、コミットメッセージを修正してcommit hashの行をつけてます。Fromの行についてはコミットメッセージには含めないで大丈夫です。これはgit-send-emailがつけてくれます。

適当なリポジトリを作って流れを試してみる

適当にリポジトリを作って流れを見てみましょう。branchはこんな感じになっています。signed-offに使うメールアドレスや名前は~/.gitconfigとリポジトリ内の.git/configを使い分けてやってます。

masami@moon:~/test-prg$ git branch 
* main
  test-1.y

ここでこんなコミットを作ったとします。この段階ではAuthorはmasami256です。

commit e8757ffa89dc4aeb1dedec7f811b3fecaf4de75a (HEAD -> main)
Author: masami256 <masami256+test@gmail.com>
Date:   Sat Dec 11 19:43:35 2021 +0900

    Add show() to display argv
    
    Add new function show() to display argv values.
    
    Signed-off-by: masami256 <masami256+test@gmail.com>

git-format-patchでtest-1.yブランチ向けにpatchを作ります。

masami@moon:~/test-prg$ git format-patch -1 e8757ffa89dc4aeb1dedec7f811b3fecaf4de75a test-1.y 
0001-Add-show-to-display-argv.patch

できたpatchはこのようになります。

masami@moon:~/test-prg$ cat 0001-Add-show-to-display-argv.patch 
From e8757ffa89dc4aeb1dedec7f811b3fecaf4de75a Mon Sep 17 00:00:00 2001
From: masami256 <masami256+test@gmail.com>
Date: Sat, 11 Dec 2021 19:43:35 +0900
Subject: [PATCH] Add show() to display argv

Add new function show() to display argv values.

Signed-off-by: masami256 <masami256+test@gmail.com>
---
 test.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/test.c b/test.c
index c0e2886..704995c 100644
--- a/test.c
+++ b/test.c
@@ -1,9 +1,13 @@
 #include <stdio.h>
 
-int main(int argc, char **argv)
+void show(char **av)
 {
-       while (*argv)
-               printf("%s\n", *argv++);
+       while (*av)
+               printf("%s\n", *av++);
+}
 
+int main(int argc, char **argv)
+{
+       show(argv);
        return 0;
 }
-- 
2.33.1

ここで、patchが素直に当たらないようにtest-1.yブランチのコードを適当に変えてみましょう。こんな感じにします。

diff --git a/test.c b/test.c
index c0e2886..b36a1ab 100644
--- a/test.c
+++ b/test.c
@@ -2,8 +2,8 @@
 
 int main(int argc, char **argv)
 {
-       while (*argv)
-               printf("%s\n", *argv++);
+       for (int i = 0; i < argc; i++)
+               printf("%s\n", argv[i]);
 
        return 0;
 }

そして、test-1.yブランチから適当なブランチ(ここではtest-1.y-work)を作ってそこでgit-amを実行すると当然patchが当たらないのでエラーになります。

masami@moon:~/test-prg$ git am --reject 0001-Add-show-to-display-argv.patch
Applying: Add show() to display argv
Checking patch test.c...
error: while searching for:
#include <stdio.h>

int main(int argc, char **argv)
{
        while (*argv)
                printf("%s\n", *argv++);

        return 0;
}

error: patch failed: test.c:1
Applying patch test.c with 1 reject...
Rejected hunk #1.
Patch failed at 0001 Add show() to display argv
hint: Use 'git am --show-current-patch=diff' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

--rejectオプションをつけてるので.rejファイルもできてます。

masami@moon:~/test-prg$ cat test.c.rej 
diff a/test.c b/test.c  (rejected hunks)
@@ -1,9 +1,13 @@
 #include <stdio.h>
 
-int main(int argc, char **argv)
+void show(char **av)
 {
-       while (*argv)
-               printf("%s\n", *argv++);
+       while (*av)
+               printf("%s\n", *av++);
+}
 
+int main(int argc, char **argv)
+{
+       show(argv);
        return 0;
 }

それはさておき、0001-Add-show-to-display-argv.patchを適用するようにコードを修正しましょう。。。

masami@moon:~/test-prg$ git am --continue
Applying: Add show() to display argv

コミットメッセージを修正します。

masami@moon:~/test-prg$ git commit --amend -s

こんな感じのコミットメッセージにしました。commit hashを足したのと、最下部のsigned-offは-sオプションでついたもの、その上のfix ~は自分で書いたものです。

commit 870abfd3042fb950e59c4f1ad9e156d0b68df259 (HEAD -> test-1.y-work)
Author: masami256 <masami256+test@gmail.com>
Date:   Sat Dec 11 19:43:35 2021 +0900

    Add show() to display argv
    
    commit e8757ffa89dc4aeb1dedec7f811b3fecaf4de75a upstream.
    
    Add new function show() to display argv values.
    
    Signed-off-by: masami256 <masami256+test@gmail.com>
    [fix conflict to use show()]
    Signed-off-by: Masami Ichikawa <masami256@gmail.com>

test-1.yブランチ向けにgit-format-patchでpatchを再作成します。

masami@moon:~/test-prg$ git format-patch -1 870abfd3042fb950e59c4f1ad9e156d0b68df259 test-1.y
0001-Add-show-to-display-argv.patch
masami@moon:~/test-prg$ cat 0001-Add-show-to-display-argv.patch
From 870abfd3042fb950e59c4f1ad9e156d0b68df259 Mon Sep 17 00:00:00 2001
From: masami256 <masami256+test@gmail.com>
Date: Sat, 11 Dec 2021 19:43:35 +0900
Subject: [PATCH] Add show() to display argv

commit e8757ffa89dc4aeb1dedec7f811b3fecaf4de75a upstream.

Add new function show() to display argv values.

Signed-off-by: masami256 <masami256+test@gmail.com>
[fix conflict to use show()]
Signed-off-by: Masami Ichikawa <masami256@gmail.com>
---
 test.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/test.c b/test.c
index 4f83ff9..704995c 100644
--- a/test.c
+++ b/test.c
@@ -1,9 +1,13 @@
 #include <stdio.h>
 
-int main(int argc, char **argv)
+void show(char **av)
 {
-       for (int i; i < argc; i++)
-               printf("%s\n", argv[i]);
+       while (*av)
+               printf("%s\n", *av++);
+}
 
+int main(int argc, char **argv)
+{
+       show(argv);
        return 0;
 }
-- 
2.33.1

これをgit-send-emailでメールします。

masami@moon:~/test-prg$ git send-email --to=masami256+test@gmail.com ./0001-Add-show-to-display-argv.patch
./0001-Add-show-to-display-argv.patch
(mbox) Adding cc: masami256 <masami256+test@gmail.com> from line 'From: masami256 <masami256+test@gmail.com>'
(body) Adding cc: masami256 <masami256+test@gmail.com> from line 'Signed-off-by: masami256 <masami256+test@gmail.com>'
(body) Adding cc: Masami Ichikawa <masami256@gmail.com> from line 'Signed-off-by: Masami Ichikawa <masami256@gmail.com>'

From: Masami Ichikawa <masami256@gmail.com>
To: masami256+test@gmail.com
Cc: Masami Ichikawa <masami256@gmail.com>
Subject: [PATCH] Add show() to display argv
Date: Sat, 11 Dec 2021 20:37:23 +0900
Message-Id: <20211211113723.79728-1-masami256@gmail.com>
X-Mailer: git-send-email 2.33.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

    The Cc list above has been expanded by additional
    addresses found in the patch commit message. By default
    send-email prompts before sending whenever this occurs.
    This behavior is controlled by the sendemail.confirm
    configuration setting.

    For additional information, run 'git send-email --help'.
    To retain the current behavior, but squelch this message,
    run 'git config --global sendemail.confirm auto'.

Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): 

まず、e[dit]でメールのサブジェクトを変更します。

From 870abfd3042fb950e59c4f1ad9e156d0b68df259 Mon Sep 17 00:00:00 2001
From: masami256 <masami256+test@gmail.com>
Date: Sat, 11 Dec 2021 19:43:35 +0900
Subject: [PATCH for test-1.y] Add show() to display argv

commit e8757ffa89dc4aeb1dedec7f811b3fecaf4de75a upstream.

Add new function show() to display argv values.

Signed-off-by: masami256 <masami256+test@gmail.com>
[fix conflict to use show()]
Signed-off-by: Masami Ichikawa <masami256@gmail.com>

この時点では送信するpatchのコミットメッセージはオリジナルのままです。 変更したらエディタを終了してメニューに戻ります。そして、y[es]で送信しましょう。

(mbox) Adding cc: masami256 <masami256+test@gmail.com> from line 'From: masami256 <masami256+test@gmail.com>'
(body) Adding cc: masami256 <masami256+test@gmail.com> from line 'Signed-off-by: masami256 <masami256+test@gmail.com>'
(body) Adding cc: Masami Ichikawa <masami256@gmail.com> from line 'Signed-off-by: Masami Ichikawa <masami256@gmail.com>'

From: Masami Ichikawa <masami256@gmail.com>
To: masami256+test@gmail.com
Cc: Masami Ichikawa <masami256@gmail.com>
Subject: [PATCH for test-1.y] Add show() to display argv
Date: Sat, 11 Dec 2021 20:37:24 +0900
Message-Id: <20211211113723.79728-1-masami256@gmail.com>
X-Mailer: git-send-email 2.33.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): y
OK. Log says:
Server: smtp.gmail.com
MAIL FROM:<masami256@gmail.com>
RCPT TO:<masami256+test@gmail.com>
RCPT TO:<masami256@gmail.com>
From: Masami Ichikawa <masami256@gmail.com>
To: masami256+test@gmail.com
Cc: Masami Ichikawa <masami256@gmail.com>
Subject: [PATCH for test-1.y] Add show() to display argv
Date: Sat, 11 Dec 2021 20:37:24 +0900
Message-Id: <20211211113723.79728-1-masami256@gmail.com>
X-Mailer: git-send-email 2.33.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

Result: 250 

届いたメールを確認するとこのようになっていて、Fromの行が先頭に追加され、ここはオリジナルのAuthorが設定されているのがわかります。

f:id:masami256:20211211203912p:plain
mail

ここまでの手順をstable kernelの場合も行うことになります。

メーリングリストにpatchを送る

git-format-patchでpatchが作れたらあとはメールを送るだけです。もし、バックポート対象のpatchがバックポートしたいブランチに当てるのに失敗していた場合はloreの該当メールにgit-send-emailでpatchを送る方法が書かれています。こんな感じで。なので指示の通りにメールを送りましょう。そうでない場合はmainlineにpatchを送るときと同様に必要な宛先を調べてto、ccをセットしましょう。

まとめ

この記事ではstable kernelにpatchをバックポートする流れを紹介してみました。どんなpatchをバックポートするかですが、自分は CIP Kernel Team: Helping CIP Sustain Industrial Grade Systemsのkernel teamの作業の一環として脆弱性の修正をバックポートする感じでやってます。