システムコールに関するlibseccompエラーの戻り値を見ると、次の理由のどれがエラーの原因であるかを判別できません。
seccompフィルターを作成するとき、呼び出し元はこれらの理由のいくつかを致命的と見なす可能性がありますが、他の理由は考慮しない可能性があるため、より詳細なエラー情報( -EINVAL
よりも幅広いエラー値のセット)が必要になります。
systemd PR6952も参照してください。
こんにちは@topimiettinen 、申し訳ありませんが、これに到達するのに非常に時間がかかりましたが、これを修正する時が来たと思います。
@drakenclimberこれはやっかいなことになります。 すべてのlibseccompAPIには、この時点でマンページが必要です(必要がない場合は、問題を作成する必要があります)。すべてのマンページには、RETURNVALUEセクションに手で波打つ「エラー時の負の値」コメントがあります。 私たちは次のことをする必要があると思います:
考え?
こんにちは@topimiettinen 、申し訳ありませんが、これに到達するのに非常に時間がかかりましたが、これを修正する時が来たと思います。
@drakenclimberこれはやっかいなことになります。 すべてのlibseccompAPIには、この時点でマンページが必要です(必要がない場合は、問題を作成する必要があります)。すべてのマンページには、RETURNVALUEセクションに手で波打つ「エラー時の負の値」コメントがあります。 私たちは次のことをする必要があると思います:
* manually audit each API call to generate a list of possible return values * decide if these return values make sense, modify the code if they don't * document each possible return value in the associated manpage with a brief explanation of what the error code indicates
考え?
ダン....私はあなたが上に書いたすべて、特に必要な努力に惜しみなく同意します:)。 リターンコードを正しく取得し、それらを文書化することは、非常に大きな作業になります。
はい、魅力的な仕事ではありませんが、それは重要だと思います。 私はいくつかのcgroupに取り組んできましたが、最近、cgroupの機能を完全に誤解しているコンテナーの実装に遭遇しました...しかし、カーネルやその他の場所に適切にガイドするための明確なドキュメントがなかったため、最高の状態で機能しました。彼らはできた。
この問題に関する活動を見るのは素晴らしいことです! 私は徹底的なレビューに反対していませんが、元の要求は、ある程度直交しているさまざまな障害モードを区別できるようにするためだけに制限されていました。 レビューは確かに役立つでしょう、私が思う程度の前提条件でさえ。
この問題に関する活動を見るのは素晴らしいことです! 私は徹底的なレビューに反対していませんが、元の要求は、ある程度直交しているさまざまな障害モードを区別できるようにするためだけに制限されていました。 レビューは確かに役立つでしょう、私が思う程度の前提条件でさえ。
ある時点でレビューを行う必要がありますが、今もそうかもしれません。 保留が長ければ長いほど、呼び出し元にとってエラーコードの有用性は低くなります。libseccompの全体的なポイントは、このようなものを使いやすくすることです:)
ダン....私はあなたが上に書いたすべて、特に必要な努力に惜しみなく同意します:)。 リターンコードを正しく取得し、それらを文書化することは、非常に大きな作業になります。
ええ、これがこの問題が長い間続いている理由の1つですが、私はそれを十分に延期してきました(少なくとも、 @ drakenclimberは1年未満延期していると言えます!)。 今日の後半(明日?)、これをチャンク/複数の問題(いくつかの提案を含む)に分割して、少しずつ簡単に取り組むことができるようにします。
少し前向きなことですが、libseccompは実際には9つの一意のerrno値のみを使用しているように見えます(非常に大雑把なチェックによると)。
# grep -e "-E[A-Z0-9]\+" src/*.{h,c} | sed 's/.*-\(E[A-Z0-9]\+\).*/\1/' | sort -u
EACCES
EDOM
EEXIST
EFAULT
EINVAL
ENOMEM
EOPNOTSUPP
EPERM
ESRCH
...これは、問題領域を少し縮小するのに役立つはずです。特に、ライブラリ全体の各エラーコードに共通のセマンティック値に同意できる場合はそうです(これは間違いなく行う必要があります)。
これは意図したものより少し遅れていますが、libseccompAPIを構成する関数の完全なリストは次のとおりです。
const struct scmp_version *seccomp_version(void)
unsigned int seccomp_api_get(void)
int seccomp_api_set(unsigned int level)
scmp_filter_ctx seccomp_init(uint32_t def_action)
int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)
void seccomp_release(scmp_filter_ctx ctx)
int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src)
uint32_t seccomp_arch_resolve_name(const char *arch_name)
uint32_t seccomp_arch_native(void)
int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token)
int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
int seccomp_load(const scmp_filter_ctx ctx)
int seccomp_attr_get(const scmp_filter_ctx ctx, enum scmp_filter_attr attr, uint32_t *value)
int seccomp_attr_set(scmp_filter_ctx ctx, enum scmp_filter_attr attr, uint32_t value)
char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num)
int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)
int seccomp_syscall_resolve_name_rewrite(uint32_t arch_token, const char *name)
int seccomp_syscall_resolve_name(const char *name)
int seccomp_syscall_priority(scmp_filter_ctx ctx, int syscall, uint8_t priority)
int seccomp_rule_add_array(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array)
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...)
int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array)
int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...)
int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp)
void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp)
int seccomp_notify_receive(int fd, struct seccomp_notif *req)
int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp)
int seccomp_notify_id_valid(int fd, uint64_t id)
int seccomp_notify_fd(const scmp_filter_ctx ctx)
int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
...これらの関数のうち、「int」を返す関数についてのみ心配する必要があります。
同様のコードパスと戻り値を持つ必要がある関数の可能なグループ。
int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token)
int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
int seccomp_attr_get(const scmp_filter_ctx ctx, enum scmp_filter_attr attr, uint32_t *value)
int seccomp_attr_set(scmp_filter_ctx ctx, enum scmp_filter_attr attr, uint32_t value)
int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)
int seccomp_syscall_resolve_name_rewrite(uint32_t arch_token, const char *name)
int seccomp_syscall_resolve_name(const char *name)
int seccomp_rule_add_array(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array)
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...)
int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array)
int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...)
int seccomp_notify_receive(int fd, struct seccomp_notif *req)
int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp)
int seccomp_notify_id_valid(int fd, uint64_t id)
int seccomp_notify_fd(const scmp_filter_ctx ctx)
int seccomp_load(const scmp_filter_ctx ctx)
int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
...関数が上記のグループのいずれにも属していない場合は、コードパスや戻り値が一意である可能性があります。
グループCは__NR_SCMP_ERRORのみを返します。
グループDは、EINVAL、EPERM、EOPNOTSUPP、ENOMEM、EDOM、EFAULT、EEXISTのいずれかを返すことができます。
seccomp_load()は、prctl()(PR_SET_NO_NEW_PRIVSおよびPR_SET_SECCOMPのEACCES、EFAULT、EINVALのみ)およびseccomp()(EACCES、EFAULT、EINVAL、ENOMEM、ESRCH)システムコールからEINVAL、ENOMEM、ESRCHおよびerrno値を返すことができます。ページ。
libseccompがsyscallエラーを呼び出し元に返す場合(prctl()やseccomp()など)、libseccompが影響を受けないように、単一のerrno値(おそらくENOSYS?)の背後にそれらを隠す必要があると思います。カーネルの変更(またはABIの違い)。
これがデバッグの問題になる場合は、errno値を呼び出し元に直接返す新しいattrを導入できます。
可能性はありますが、libseccompのユーザーがすでに特定のerrno値を期待している場合は、ABI / APIの破損がないことを確認すると便利です。 元の問題は、一部のシステムコールが一部のアーキテクチャ(x86_32のみのugetrlimit
など)にのみ存在することでしたが、これはタイプミスのシステムコール名と区別できなかったため、異なる(おそらく合成の)エラーコードが必要になります。
さて、前に述べたように、私たちは現在、特定のerrno値を実際に保証するのではなく、単に「失敗時の負の値」であるため、特定のerrno値について現在仮定しているユーザーを破ることは残念ですが、状況を変えると思います将来、カーネルバージョンとABI全体で強力なerrno保証を提供することは、価値のあるトレードオフです。
さて、前に述べたように、私たちは現在、特定のerrno値を実際に保証するのではなく、単に「失敗時の負の値」であるため、特定のerrno値について現在仮定しているユーザーを破ることは残念ですが、状況を変えると思います将来、カーネルバージョンとABI全体で強力なerrno保証を提供することは、価値のあるトレードオフです。
同意します。
この評価が完了し、失敗時にerrno値を更新すると、返されるerrno値を何らかの形で保証できるようになります。
グループ化のアイデアはおそらく最善ではなかったので、これをすべて追跡するためにリストを開始しましょう_(進行するにつれてこれを更新し続けます)_:
[x] seccomp_reset
現在、EINVAL、ENOMEMが返されます。
[x] seccomp_merge
現在返されるのは、EINVAL、EDOM、EEXIST、ENOMEMです。
[x] seccomp_arch_exist
現在、EINVAL、EEXISTが返されます。
[x] seccomp_arch_add
現在返されるのは、EINVAL、EEXIST、ENOMEM、EDOMです。
[x] seccomp_arch_remove
現在、EINVAL、EEXISTが返されます。
[x] seccomp_load
現在、EINVAL、ENOMEM、ESRCH、ECANCELEDが返されます。
[x] seccomp_attr_get
現在、EINVAL、EEXISTが返されます。
[x] seccomp_attr_set
現在の返品:EINVAL、EACCES、EOPNOTSUPP、EEXIST。
[x] seccomp_syscall_resolve_name_arch
すでに明確に定義されており、失敗時にsyscall値または__NR_SCMP_ERRORを返します。
[x] seccomp_syscall_resolve_name_rewrite
すでに明確に定義されており、失敗時にsyscall値または__NR_SCMP_ERRORを返します。
[x] seccomp_syscall_resolve_name
すでに明確に定義されており、失敗時にsyscall値または__NR_SCMP_ERRORを返します。
[x] seccomp_syscall_priority
現在、EINVAL、EDOM、EFAULT、ENOMEMが返されます。
[x] seccomp_rule_add_array
現在返されるのは、EINVAL、EOPNOTSUPP、ENOMEM、EDOM、EFAULT、EEXISTです。
[x] seccomp_rule_add
現在返されるのは、EINVAL、EOPNOTSUPP、ENOMEM、EDOM、EFAULT、EEXISTです。
[x] seccomp_rule_add_exact_array
現在返されるのは、EINVAL、EOPNOTSUPP、ENOMEM、EDOM、EFAULT、EEXISTです。
[x] seccomp_rule_add_exact
現在返されるのは、EINVAL、EOPNOTSUPP、ENOMEM、EDOM、EFAULT、EEXISTです。
[x] seccomp_notify_alloc
現在の返品:EOPNOTSUPP、ENOMEM、EFAULT、ECANCELED。 マンページでは、エラー時に-1がすでに指定されています。これは、seccomp()errnoのみを参照している可能性があります。
[x] seccomp_notify_receive
現在の返品:EOPNOTSUPPおよびECANCELED。 マンページでは、エラー時に-1がすでに指定されています。これは、seccomp()errnoのみを参照している可能性があります。
[x] seccomp_notify_respond
現在の返品:EOPNOTSUPPおよびECANCELED。 マンページでは、エラー時に-1がすでに指定されています。これは、seccomp()errnoのみを参照している可能性があります。
[x] seccomp_notify_id_valid
現在の返品:EOPNOTSUPPおよびECANCELED。 マンページには、エラー時の-ENOENT(無効なID)がすでに指定されています。これは、seccomp()errnoのみを参照している可能性があります。
[x] seccomp_notify_fd
すでに明確に定義されており、通知fdを返します。
[x] seccomp_export_pfc
現在、EINVALおよびECANCELEDが返されます。
[x] seccomp_export_bpf
現在、EINVAL、ENOMEM、およびECANCELEDが返されます。
これで、どの関数がどのエラーコードを返すかのリストができたので、特にエラーコードの使用方法とかなり一貫しているので、これについて少し気分が良くなりました。 その最後のビットは非常に役立つはずです。
PRを開始して、修正と変更に関するフィードバックの収集を開始できるようにします。すぐにここに投稿します。
ENOSYSのかなり「特別な」性質を考えると、カーネル/ libcのキャッチオールとしてerrnoを使用することについては留保しています。 私は他の価値観を見なければなりません、誰かがこれについて強い感情/考えを持っていますか?
まだ多くの欠落があり、ほとんどがマンページの編集とコードコメント(テストは言うまでもなく)ですが、次のブランチを見て、私が何を考えているかを理解することができます。
ENOSYSのかなり「特別な」性質を考えると、カーネル/ libcのキャッチオールとしてerrnoを使用することについては留保しています。 私は他の価値観を見なければなりません、誰かがこれについて強い感情/考えを持っていますか?
EIOはどうですか?
EIOはどうですか?
それがエラーをはるかに実行可能にするかどうかはわかりません。 代わりに、errno値を使用しない関数でAPIを拡張するのはどうでしょうか。ただし、たとえば、次のようになります。
または、errnosを使用したAPIをそのままにしておくこともできますが、新しい関数を使用して上記のエラーコードを要求することもできます。
おそらく、 @ poetteringまたは@keszybzもコメントできます。
それがエラーをはるかに実行可能にするかどうかはわかりません。 代わりに、errno値を使用しない関数でAPIを拡張するのはどうですか...
そうですね、そのようなことを検討する前に(そして、それを実行したいかどうかはわかりませんが)、安定したサポートされているリターンコードを決定する必要があります。 これが私たちがここで取り組んでいることであり、v2.5を対象としています。
v2.5で安定した/サポートされているリターンコードを取得してみましょう。それがどのように行われるかを確認できます。さらに何かを行う必要がある場合は、v2.6でそれを検討できます。
EIOはどうですか?
他の作業の優先順位やいくつかのカーネルの問題のためにしばらくこれをやめましたが、libseccompに戻ったので、ここでEIOを使用するのは間違っているように思えます。 これについてもう少し考えさせてください。
キャッチオールカーネルエラーコードとしてのECANCELEDはどうですか?
私はあなたが@drakenclimberをどう思うか興味があります、あなたはこれについてしばらく静かにしています。
他の作業の優先順位やいくつかのカーネルの問題のためにしばらくこれをやめましたが、libseccompに戻ったので、ここでEIOを使用するのは間違っているように思えます。 これについてもう少し考えさせてください。
こっちも一緒。 最近は少し忙しいです:/。
私はあなたが@drakenclimberをどう思うか興味があります、あなたはこれについてしばらく静かにしています。
もちろん。 スレッド全体をもう一度読みたいので、チャイムを鳴らします。
キャッチオールカーネルエラーコードとしてのECANCELEDはどうですか?
私はECANCELEDにあまり精通していなかったことを認めます。 カーネルソースの使用法を簡単に調べ、グーグル検索も行いました。 ECANCELEDは、以前に使用したlibseccomp、prctl()、またはその他のAPIとの衝突はなく、カーネルがスローするエラーを合理的にカプセル化できると思います。
tl; dr-カーネルエラーのキャッチオールとしてECANCELEDを使用するのはかっこいいです。
まことにありがとうございます。 中途半端なパッチセットを持っています。仕上げて、レビュー用のPRとして提出します。
最も参考になるコメント
まことにありがとうございます。 中途半端なパッチセットを持っています。仕上げて、レビュー用のPRとして提出します。