├── stable_kernel_version ├── renovate.json ├── .whitesource ├── .eslintignore ├── .prettierignore ├── Dockerfile ├── Makefile ├── .github ├── workflows │ ├── todo.yml │ ├── codeball.yml │ ├── label-sync.yml │ ├── lint-pr-actions.yml │ ├── pr-labeller.yml │ ├── lint-pr-markdown.yml │ └── lint-pr-actions-skip.yml ├── PULL_REQUEST_TEMPLATE.md ├── renovate.json └── config │ ├── labels.yml │ └── labeller.yml ├── .gitlab-ci.yml ├── .travis.yml ├── .editorconfig ├── kernel_watch.sh ├── LICENSE ├── example_patches ├── CVE20176074.patch ├── dirtyCOW.patch └── stackclash.patch ├── .gitignore ├── kernel_config.sh └── README.md /stable_kernel_version: -------------------------------------------------------------------------------- 1 | 4.6.3 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "baseBranches": [] 4 | }, 5 | "checkRunSettings": { 6 | "vulnerableCheckRunConclusionLevel": "failure", 7 | "displayMode": "diff", 8 | "useMendCheckNames": true 9 | }, 10 | "issueSettings": { 11 | "minSeverityLevel": "MEDIUM", 12 | "issueType": "DEPENDENCY" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | .ide 4 | .idea 5 | .vscode 6 | **/__pycache__ 7 | **/__pypackages__ 8 | **/.bin 9 | **/.DS_Store 10 | **/.env.* 11 | **/.git 12 | **/.out 13 | **/.venv 14 | **/*.log 15 | **/*.tmp 16 | **/build 17 | **/cdk.out 18 | **/coverage 19 | **/dist 20 | **/global.setup.ts 21 | **/htmlcov 22 | **/logs 23 | **/node_modules 24 | **/public 25 | **/temp 26 | **/tmp 27 | **/venv 28 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | .ide 4 | .idea 5 | .vscode 6 | **/__pycache__ 7 | **/__pypackages__ 8 | **/.bin 9 | **/.DS_Store 10 | **/.env.* 11 | **/.git 12 | **/.out 13 | **/.venv 14 | **/*.log 15 | **/*.tmp 16 | **/build 17 | **/cdk.out 18 | **/coverage 19 | **/dist 20 | **/global.setup.ts 21 | **/htmlcov 22 | **/logs 23 | **/node_modules 24 | **/public 25 | **/temp 26 | **/tmp 27 | **/venv 28 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:wheezy 2 | MAINTAINER Sam McLeod 3 | 4 | ENV DEBIAN_FRONTEND noninteractive 5 | 6 | # Install Debian packages 7 | RUN apt-get -y update && apt-get -y install openssh-client coreutils fakeroot build-essential kernel-package wget xz-utils gnupg bc devscripts apt-utils initramfs-tools aria2 curl && apt-get clean 8 | RUN mkdir -p /mnt/storage 9 | 10 | WORKDIR /app 11 | 12 | ADD * /app/ 13 | 14 | RUN chmod +x buildkernel.sh && ./buildkernel.sh 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAME = linux-kernel 2 | REPO = contyard.yourcompany.com/$(NAME) 3 | TAG = $(git describe) 4 | 5 | build: 6 | docker build -t $(REPO):$(TAG) . 7 | @echo "Successfully built $(REPO):$(TAG)..." 8 | @echo "make push" 9 | 10 | push: 11 | docker run -v /mnt/storage/:/mnt/storage $(REPO):$(TAG) bash -c "cp *.deb /mnt/storage/" 12 | 13 | clean: 14 | docker rmi -f $(REPO):$(TAG) 15 | 16 | ci: 17 | @echo RUNNING ON `hostname` 18 | @echo RUNNING AS `whoami` 19 | make build 20 | make push 21 | make clean 22 | -------------------------------------------------------------------------------- /.github/workflows/todo.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Check for TODOs and create or update issues" 4 | 5 | on: ["push"] 6 | 7 | permissions: 8 | issues: write 9 | contents: read 10 | 11 | # One build per branch, cancel out of date builds 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | todo-issues: 18 | runs-on: "ubuntu-latest" 19 | steps: 20 | - uses: "actions/checkout@v3" 21 | - name: "Check for TODOs and create or update issues" 22 | uses: "alstr/todo-to-issue-action@v4" 23 | id: "todo" 24 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | job1: 2 | before_script: 3 | - apt-get update || true 4 | - apt-get install -y python-software-properties build-essential kernel-package autoconf ruby2.1 rubygems-integration sudo ruby 5 | - apt-get install -y gcc-4.9 g++-4.9 6 | - update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20 7 | - update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20 8 | - update-alternatives --config gcc 9 | - update-alternatives --config g++ 10 | - gem install package_cloud 11 | 12 | variables: 13 | APT_UPDATE: "true" 14 | # KERNEL_VERSION: "4.6.4" 15 | 16 | script: 17 | - ./buildkernel.sh 18 | -------------------------------------------------------------------------------- /.github/workflows/codeball.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: Codeball 4 | 5 | on: 6 | pull_request: 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | issues: write 12 | pull-requests: write 13 | checks: write 14 | 15 | jobs: 16 | codeball-review: 17 | runs-on: ubuntu-latest 18 | name: Run Codeball Code Review 19 | steps: 20 | - name: Codeball AI Actions 21 | uses: sturdy-dev/codeball-action@v2 22 | with: 23 | approvePullRequests: "false" 24 | labelPullRequestsWhenApproved: "true" 25 | labelPullRequestsWhenReviewNeeded: "true" 26 | failJobsWhenReviewNeeded: "false" 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | env: 4 | - GRSEC=true 5 | - GRSEC=false 6 | 7 | before_install: 8 | - gem install package_cloud 9 | - sudo apt-get install -y python-software-properties 10 | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 11 | - sudo apt-get update || true 12 | - sudo apt-get install -y gcc-4.8 g++-4.8 13 | - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20 14 | - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 20 15 | - sudo update-alternatives --config gcc 16 | - sudo update-alternatives --config g++ 17 | 18 | script: 19 | - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers 20 | - sudo -E ./buildkernel.sh 21 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # EditorConfig https://EditorConfig.org 4 | 5 | # top-most EditorConfig file 6 | root = true 7 | 8 | # Unix-style newlines with a newline ending every file 9 | [*] 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | charset = utf-8 14 | 15 | # Ensure we're standardising on 2 space soft-tabs for most files 16 | [*.md, *.markdown, *.yml, *.yaml, *.json, *.js, *.ts, *.tsx, *.sh] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | # Makefile specific 21 | [Makefile] 22 | indent_style = tab 23 | indent_size = 4 24 | 25 | # Python specific 26 | [*.py, *.pyi] 27 | indent_style = space 28 | indent_size = 4 29 | -------------------------------------------------------------------------------- /kernel_watch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # 3 | # Author: Sam McLeod - github.com/sammcj 4 | # 5 | # 1. Checks out a git repo 6 | # 2. Checks the latest stable kernel from kernel.org 7 | # 3. If there are any changes they will be added, commited and pushed 8 | # 4. This will trigger a Travis-CI run that will in turn build a Debian package of the kernel 9 | # 5. And upload the successful build to packagecloud.io 10 | 11 | git reset --hard HEAD 12 | git pull 13 | 14 | curl --silent https://www.kernel.org/finger_banner | awk '/ stable /{print $(NF)}' | tail -1 > stable_kernel_version 15 | 16 | git add stable_kernel_version 17 | git commit -m "Bumping kernel to version $(cat stable_kernel_version)" --author="Kernel Watch " || true 18 | git push 19 | -------------------------------------------------------------------------------- /.github/workflows/label-sync.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Sync Available Github Labels" 4 | 5 | on: 6 | workflow_dispatch: 7 | schedule: 8 | - cron: "30 4 * * *" 9 | 10 | permissions: 11 | pull-requests: write 12 | contents: read 13 | 14 | # One build per branch, cancel out of date builds 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.ref }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | sync-labels: 21 | name: Sync Github Labels 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v3 25 | - uses: EndBug/label-sync@v2 26 | with: 27 | delete-other-labels: true 28 | dry-run: false 29 | token: ${{ secrets.GITHUB_TOKEN }} 30 | config-file: .github/config/labels.yml 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # 6 | 7 | ## Breaking Changes 8 | 9 | Are there any breaking changes in this PR, If yes, please list them. 10 | 11 | ## How Has This Been Tested? 12 | 13 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 14 | 15 | - Test 1 16 | - Test 2 17 | 18 | ## Checklist 19 | 20 | - [ ] I have performed a self-review of my own code. 21 | - [ ] I have commented my code, particularly in hard-to-understand areas. 22 | - [ ] I have made corresponding changes to the documentation. 23 | - [ ] My changes generate no new warnings. 24 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-actions.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint Github Actions Workflows" 4 | on: 5 | pull_request: 6 | types: 7 | - opened 8 | - edited 9 | - reopened 10 | - synchronize 11 | branches: 12 | - "main" 13 | paths: 14 | - ".github/**" 15 | 16 | permissions: 17 | contents: read 18 | pull-requests: write 19 | checks: write 20 | 21 | jobs: 22 | lint-actions-workflows: 23 | name: Lint Actions Workflows 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v3 27 | - uses: reviewdog/action-actionlint@v1 28 | with: 29 | actionlint_flags: -color -ignore 'SC2086' -ignore 'SC2129' 30 | fail_on_error: false 31 | level: error 32 | reporter: github-pr-review 33 | env: 34 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.github/workflows/pr-labeller.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Pull Request Labeller" 4 | on: 5 | pull_request: 6 | types: 7 | - opened 8 | - edited 9 | - reopened 10 | - synchronize 11 | - ready_for_review 12 | branches: 13 | - main 14 | - master 15 | issues: 16 | issue_comment: 17 | 18 | # One build per branch, cancel out of date builds 19 | concurrency: 20 | group: ${{ github.workflow }}-${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | permissions: 24 | issues: write 25 | pull-requests: write 26 | statuses: write 27 | checks: write 28 | contents: read 29 | 30 | jobs: 31 | pr-labeller: 32 | name: "Pull Request Labeller" 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: fuxingloh/multi-labeler@v1 36 | id: pr-labeller 37 | with: 38 | github-token: ${{ secrets.GITHUB_TOKEN }} 39 | config-path: .github/config/labeller.yml 40 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-markdown.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: Lint Markdown Files 4 | 5 | # https://github.com/reviewdog/action-markdownlint 6 | 7 | on: 8 | pull_request: 9 | workflow_dispatch: 10 | 11 | permissions: 12 | contents: read 13 | checks: write 14 | pull-requests: write 15 | 16 | # One build per branch, cancel out of date builds 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | lint-markdown: 23 | name: Lint Markdown 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v3 27 | - name: markdownlint 28 | uses: reviewdog/action-markdownlint@v0 29 | with: 30 | github_token: ${{ secrets.GITHUB_TOKEN }} 31 | reporter: github-pr-review 32 | level: error 33 | filter_mode: added 34 | fail_on_error: false 35 | ### Flags for markdownlint-cli ### 36 | # markdownlint_flags: . 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Sam McLeod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-actions-skip.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint Github Actions Workflows" 4 | 5 | # This is a gross hack to allow PRs that don't require a specific workflow to run (e.g. don't lint files not touched) by providing a positive status check in their place. 6 | # This workflow runs on an inverse match using the paths-ignore filter, so it will only run if the PR doesn't touch any of the paths that the other linting workflow does 7 | # The "name:" must match the name of the workflow it's skipping. 8 | # As recommended by Github - https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 9 | 10 | on: 11 | pull_request: 12 | types: 13 | - opened 14 | - edited 15 | - reopened 16 | - synchronize 17 | branches: 18 | - "main" 19 | paths-ignore: 20 | - ".github/**" 21 | 22 | jobs: 23 | lint-actions-workflows: 24 | name: Lint Actions Workflows 25 | runs-on: ubuntu-latest 26 | steps: 27 | - run: echo "This workflow is a placeholder for PRs that don't require linting of Github Actions workflows" 28 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "commitMessagePrefix": "chore(renovate):", 4 | "description": "This file is managed in template-repo", 5 | "packageRules": [ 6 | { 7 | "matchPackagePatterns": ["*"], 8 | "matchUpdateTypes": ["major"], 9 | "reviewersFromCodeOwners": true, 10 | "addLabels": ["renovatebot", "major", "version-update"], 11 | "commitMessagePrefix": "chore(renovate): major", 12 | "groupName": "major" 13 | }, 14 | { 15 | "matchPackagePatterns": ["*"], 16 | "matchUpdateTypes": ["minor"], 17 | "reviewersFromCodeOwners": true, 18 | "addLabels": ["renovatebot", "minor", "version-update"], 19 | "commitMessagePrefix": "chore(renovate): minor", 20 | "groupName": "minor" 21 | }, 22 | { 23 | "matchPackagePatterns": ["*"], 24 | "matchUpdateTypes": ["patch"], 25 | "reviewersFromCodeOwners": true, 26 | "addLabels": ["renovatebot", "patch", "version-update"], 27 | "commitMessagePrefix": "chore(renovate): patch", 28 | "groupName": "patch" 29 | }, 30 | { 31 | "matchPackagePatterns": ["*"], 32 | "matchUpdateTypes": ["pin", "digest"], 33 | "reviewersFromCodeOwners": true, 34 | "addLabels": ["renovatebot", "pin", "version-update"], 35 | "commitMessagePrefix": "chore(renovate): pin", 36 | "groupName": "pin" 37 | } 38 | ], 39 | "vulnerabilityAlerts": { 40 | "commitMessagePrefix": "chore(renovate): Security update", 41 | "labels": ["security"] 42 | }, 43 | "ignorePaths": ["files/**", "node_modules/**"] 44 | } 45 | -------------------------------------------------------------------------------- /example_patches/CVE20176074.patch: -------------------------------------------------------------------------------- 1 | From 5edabca9d4cff7f1f2b68f0bac55ef99d9798ba4 Mon Sep 17 00:00:00 2001 2 | From: Andrey Konovalov 3 | Date: Thu, 16 Feb 2017 17:22:46 +0100 4 | Subject: [PATCH] dccp: fix freeing skb too early for IPV6_RECVPKTINFO 5 | 6 | In the current DCCP implementation an skb for a DCCP_PKT_REQUEST packet 7 | is forcibly freed via __kfree_skb in dccp_rcv_state_process if 8 | dccp_v6_conn_request successfully returns. 9 | 10 | However, if IPV6_RECVPKTINFO is set on a socket, the address of the skb 11 | is saved to ireq->pktopts and the ref count for skb is incremented in 12 | dccp_v6_conn_request, so skb is still in use. Nevertheless, it gets freed 13 | in dccp_rcv_state_process. 14 | 15 | Fix by calling consume_skb instead of doing goto discard and therefore 16 | calling __kfree_skb. 17 | 18 | Similar fixes for TCP: 19 | 20 | fb7e2399ec17f1004c0e0ccfd17439f8759ede01 [TCP]: skb is unexpectedly freed. 21 | 0aea76d35c9651d55bbaf746e7914e5f9ae5a25d tcp: SYN packets are now 22 | simply consumed 23 | 24 | Signed-off-by: Andrey Konovalov 25 | Acked-by: Eric Dumazet 26 | Signed-off-by: David S. Miller 27 | --- 28 | net/dccp/input.c | 3 ++- 29 | 1 file changed, 2 insertions(+), 1 deletion(-) 30 | 31 | diff --git net/dccp/input.c net/dccp/input.c 32 | index ba34718..8fedc2d 100644 33 | --- net/dccp/input.c 34 | +++ net/dccp/input.c 35 | @@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, 36 | if (inet_csk(sk)->icsk_af_ops->conn_request(sk, 37 | skb) < 0) 38 | return 1; 39 | - goto discard; 40 | + consume_skb(skb); 41 | + return 0; 42 | } 43 | if (dh->dccph_type == DCCP_PKT_RESET) 44 | goto discard; 45 | -------------------------------------------------------------------------------- /example_patches/dirtyCOW.patch: -------------------------------------------------------------------------------- 1 | diff --git include/linux/mm.h include/linux/mm.h 2 | index e9caec6..ed85879 100644 3 | --- include/linux/mm.h 4 | +++ include/linux/mm.h 5 | @@ -2232,6 +2232,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, 6 | #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ 7 | #define FOLL_MLOCK 0x1000 /* lock present pages */ 8 | #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ 9 | +#define FOLL_COW 0x4000 /* internal GUP flag */ 10 | 11 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, 12 | void *data); 13 | diff --git mm/gup.c mm/gup.c 14 | index 96b2b2f..22cc22e 100644 15 | --- mm/gup.c 16 | +++ mm/gup.c 17 | @@ -60,6 +60,16 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address, 18 | return -EEXIST; 19 | } 20 | 21 | +/* 22 | + * FOLL_FORCE can write to even unwritable pte's, but only 23 | + * after we've gone through a COW cycle and they are dirty. 24 | + */ 25 | +static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) 26 | +{ 27 | + return pte_write(pte) || 28 | + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); 29 | +} 30 | + 31 | static struct page *follow_page_pte(struct vm_area_struct *vma, 32 | unsigned long address, pmd_t *pmd, unsigned int flags) 33 | { 34 | @@ -95,7 +105,7 @@ retry: 35 | } 36 | if ((flags & FOLL_NUMA) && pte_protnone(pte)) 37 | goto no_page; 38 | - if ((flags & FOLL_WRITE) && !pte_write(pte)) { 39 | + if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) { 40 | pte_unmap_unlock(ptep, ptl); 41 | return NULL; 42 | } 43 | @@ -412,7 +422,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, 44 | * reCOWed by userspace write). 45 | */ 46 | if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE)) 47 | - *flags &= ~FOLL_WRITE; 48 | + *flags |= FOLL_COW; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /.github/config/labels.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # .github/config/labels.yml 4 | 5 | - name: "Feat" 6 | color: "c52bff" 7 | aliases: ["Feature", "Features"] 8 | 9 | - name: "Fix" 10 | color: "125a29" 11 | aliases: ["bug", "bugfix", "patched", "Hotfix"] 12 | 13 | - name: "Chore" 14 | color: "293535" 15 | aliases: ["maintenance", "maint"] 16 | 17 | - name: "Docs" 18 | color: "7c9e9d" 19 | aliases: ["doco", Documentation'] 20 | 21 | - name: "CDK" 22 | color: "ce7e00" 23 | aliases: ["AWS", "cloudformation", "CFn"] 24 | 25 | - name: "Github" 26 | color: "ff1089" 27 | aliases: ["Actions", "Workflow"] 28 | 29 | - name: "Git" 30 | color: "3e6890" 31 | 32 | - name: "Test" 33 | color: "981f5c" 34 | aliases: ["testing", "tests", "Jest"] 35 | 36 | - name: "Style" 37 | color: "0018a8" 38 | aliases: ["lint", "formatting", "styling", "prettier", "eslint"] 39 | 40 | - name: "Database" 41 | color: "43e8d8" 42 | aliases: ["DB", "SQL", "Flyway", "Migrations"] 43 | 44 | - name: "Security" 45 | color: "f51100" 46 | aliases: ["sec", "vulnerability", "CVE", "vuln", "CODEOWNERS"] 47 | 48 | - name: "Performance" 49 | color: "ff825a" 50 | aliases: ["perf", "optimisation"] 51 | 52 | - name: "DO NOT MERGE" 53 | color: "d54360" 54 | aliases: ["DONT MERGE", "WIP", "Work In Progress"] 55 | 56 | - name: "renovatebot" 57 | color: "123000" 58 | aliases: ["Renovate"] 59 | 60 | - name: "minor" 61 | color: "123000" 62 | aliases: ["minor-update"] 63 | 64 | - name: "major" 65 | color: "123000" 66 | aliases: ["major-update"] 67 | 68 | - name: "patch" 69 | color: "123000" 70 | aliases: ["patch-update"] 71 | 72 | - name: "sync-files" 73 | color: "130000" 74 | 75 | - name: "codeball:needs-careful-review" 76 | color: "fde68a" 77 | description: "This PR needs careful review" 78 | aliases: ["codeball:needs-review"] 79 | 80 | - name: "codeball:approved" 81 | color: "86efac" 82 | description: "This PR has been approved by Codeball AI" 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # This is the same as ../.gitignore for JS/TS/Java/Python projects, except for the top block for files required by github-actions 4 | 5 | ### START GITHUB ACTIONS FILES ### 6 | 7 | !**/node_modules 8 | !**/dist 9 | 10 | ### END GITHUB ACTIONS FILES ### 11 | 12 | # Inverse matchs to ensure these aren't ignored 13 | !*.env.template 14 | !*.eslintrc.js 15 | !*.prettierrc.js 16 | !*.config.js 17 | 18 | # Typescipt and CDK 19 | **/*.cdk.staging 20 | **/*.d.ts 21 | **/*.tabl.json 22 | **/*.tsbuildinfo 23 | **/cdk.context.json 24 | **/cdk.out 25 | 26 | # NodeJS 27 | **/node_modules 28 | 29 | # Test and coverage output 30 | **/coverage/ 31 | **/test-report.xml 32 | .coverage.* 33 | htmlcov/ 34 | megalinter-reports/ 35 | 36 | # Editors 37 | .project 38 | .settings 39 | .springBeans 40 | **/.favorites.json 41 | **/.idea 42 | **/.vscode 43 | **/*.Session.vim 44 | **/*.sw[a-z] 45 | **/*.vim 46 | **/*.zwc 47 | **/*~ 48 | 49 | # OS generated files 50 | **/._* 51 | **/.AppleDouble 52 | **/.dccache 53 | **/.dropbox 54 | **/.dropbox.attr 55 | **/.dropbox.cache 56 | **/.DS_Store 57 | **/.DS_STORE 58 | **/.lnk 59 | **/.LSOverride 60 | **/$RECYCLE.BIN/ 61 | **/Desktop.ini 62 | **/ehthumbs.db 63 | **/Thumbs.db 64 | 65 | # Files that might appear in the root of a volume 66 | **/.com.apple.timemachine.donotpresent 67 | **/.DocumentRevisions-V100 68 | **/.fseventsd 69 | **/.Spotlight-V100 70 | **/.TemporaryItems 71 | **/.Trashes 72 | **/.VolumeIcon.icns 73 | 74 | # Directories potentially created on remote AFP share 75 | **/.apdisk 76 | **/.AppleDB 77 | **/.AppleDesktop 78 | **/Network Trash Folder 79 | **/Temporary Items 80 | 81 | # Temp files 82 | **/.temp 83 | **/.tmp 84 | tmp/ 85 | 86 | # Files that commonly contain secrets 87 | **/*.key 88 | **/*.pem 89 | **/*.pfx 90 | **/*.p12 91 | **/*.jks 92 | **/*.keystore 93 | **/*.pkcs12 94 | **/*.pkcs8 95 | **/*.pkpass 96 | **/*.secrets 97 | 98 | # git mu-repo 99 | **/.mu_repo 100 | 101 | # Local state files / misc 102 | .dynamodb/ 103 | .eslintcache 104 | .fusebox/ 105 | .grunt 106 | .lock-wscript 107 | .next 108 | .node_repl_history 109 | .npm 110 | .nuxt 111 | .nyc_output 112 | .serverless/ 113 | .vuepress/dist 114 | .yarn-integrity 115 | *.seed 116 | *.tgz 117 | **/.BUILD_COMPLETED 118 | **/.cache 119 | **/.filesystem 120 | **/.LAST_BUILD 121 | **/.local-npm 122 | **/.nyc_output 123 | **/.nycrc 124 | **/.tools 125 | **/.webassets-cache 126 | **/*.lock 127 | **/*.lock.hcl 128 | **/*.pid 129 | **/db.sqlite3 130 | **/db.sqlite3-journal 131 | bower_components 132 | jspm_packages/ 133 | lib-cov 134 | 135 | # Logs 136 | **/*.log 137 | 138 | # Build directories 139 | **/_build/ 140 | **/dist 141 | build/ 142 | out/ 143 | target/ 144 | 145 | # Python 146 | __pycache__/ 147 | __pypackages__/ 148 | .ipynb_checkpoints 149 | *$py.class 150 | celerybeat-schedule 151 | develop-eggs/ 152 | dmypy.json 153 | eggs/ 154 | ipython_config.py 155 | local_settings.py 156 | pip-delete-this-directory.txt 157 | pip-log.txt 158 | pip-wheel-metadata/ 159 | venv 160 | 161 | # Jekyll 162 | _site 163 | .jekyll-cache 164 | .jekyll-metadata 165 | .sass-cache 166 | Gemfile.lock 167 | 168 | # Windows Installer files 169 | *.cab 170 | *.msi 171 | *.msm 172 | *.msp 173 | 174 | # Bootstrap files 175 | *private*.rc 176 | redo_aliases 177 | 178 | # Docker 179 | **/docker-compose.override.y*ml 180 | -------------------------------------------------------------------------------- /.github/config/labeller.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # .github/config/labeller.yml 4 | 5 | version: v1 6 | 7 | labels: 8 | - label: "Feat" 9 | sync: true 10 | matcher: 11 | title: ".*(feat:|(IF-[0-9]+ -- (feat))).*/i" 12 | body: "(feat:.*|feature:.*)/i" 13 | branch: "(^feat\/.*)/i" 14 | baseBranch: "(^feat\/.*)/i" 15 | commits: "(^feat:.*|(IF-[0-9]+ -- (feat))).*/i" 16 | 17 | - label: "Fix" 18 | sync: true 19 | matcher: 20 | title: "(^hotfix:.*|^fix:.*|(IF-[0-9]+ -- (fix|hotfix).*))/i" 21 | body: "(hotfix:.*|fix:.*|bug:.*)/i" 22 | branch: "(^hotfix\/.*|^fix\/.*)/i" 23 | baseBranch: "(^hotfix\/.*|^fix\/.*)/i" 24 | commits: "(^hotfix:.*|^fix:.*|(IF-[0-9]+ -- (fix|hotfix).*))/i" 25 | 26 | - label: "Chore" 27 | sync: true 28 | matcher: 29 | title: "(^chore:.*|(IF-[0-9]+ -- chore.*))/i" 30 | body: "(hotfix:.*|fix:.*|bug:.*)/i" 31 | branch: "(^chore\/.*)/i" 32 | baseBranch: "(^chore\/.*)/i" 33 | commits: "(^chore:.*|(IF-[0-9]+ -- chore.*))/i" 34 | author: 35 | - "renovatebot" 36 | - "renovatebot[bot]" 37 | 38 | - label: "Docs" 39 | sync: true 40 | matcher: 41 | title: "(^docs:.*|(IF-[0-9]+ -- docs.*))/i" 42 | body: "(docs:.*|documentation:)/i" 43 | branch: "(^docs\/.*)/i" 44 | baseBranch: "(^docs\/.*)/i" 45 | commits: "(^docs:.*|(IF-[0-9]+ -- docs.*))/i" 46 | files: 47 | any: 48 | [ 49 | "**/docs/**", 50 | "**/doc/**", 51 | "**/*.md", 52 | "**/*.markdown", 53 | "**/*.rst", 54 | "**/*.txt", 55 | ] 56 | count: 57 | gte: 1 58 | lte: 1000 59 | 60 | - label: "CDK" 61 | sync: true 62 | matcher: 63 | title: "(.*cdk|(IF-[0-9]+ -- cdk).*)/i" 64 | body: ".*(cdk:|cloudformation:).*/i" 65 | branch: "(.*cdk\/.*)/i" 66 | baseBranch: "(.*cdk\/.*)/i" 67 | commits: "(.*cdk:|(IF-[0-9]+ -- cdk)).*/i" 68 | files: 69 | any: ["**/cdk/**", "**/cloudformation/**", "**/*.cdk.*", "**/*.stack.*"] 70 | count: 71 | gte: 1 72 | lte: 1000 73 | 74 | - label: "Github" 75 | sync: true 76 | matcher: 77 | title: "(^actions:.*|(IF-[0-9]+ -- actions.*)|^workflow:.*|(IF-[0-9]+ -- workflow.*)|.*github:.*|(IF-[0-9]+ -- github.*))/i" 78 | body: ".*(actions:.*|github-actions:|github:|workflow:).*/i" 79 | branch: "(^actions\/.*|^github\/.*^workflow\/.*)/i" 80 | baseBranch: "(^actions\/.*|^github\/.*^workflow\/.*)/i" 81 | commits: "(^actions:.*|(IF-[0-9]+ -- actions.*)|^workflow:.*|(IF-[0-9]+ -- workflow.*)|^github:.*|(IF-[0-9]+ -- github.*))/i" 82 | files: 83 | any: [".github\/*", "CODEOWNERS"] 84 | count: 85 | gte: 1 86 | lte: 1000 87 | 88 | - label: "Test" 89 | sync: true 90 | matcher: 91 | title: "(^test|(IF-[0-9]+ -- test)|jest).*/i" 92 | body: ".*(tests:|test:|testing:|jest:).*/i" 93 | branch: "(^test\/.*)/i" 94 | baseBranch: "(^test\/.*)/i" 95 | commits: "(^tests:.*|^test:.*|(IF-[0-9]+ -- test.*))/i" 96 | files: 97 | any: ["**/.*(test|.spec).*", "**/.*jest.*"] 98 | count: 99 | gte: 1 100 | lte: 1000 101 | 102 | - label: "Performance" 103 | sync: true 104 | matcher: 105 | title: "(^perf:|(IF-[0-9]+ -- perf)).*/i" 106 | body: "(perf:|performance:).*/i" 107 | branch: "(^perf\/.*)/i" 108 | baseBranch: "(^perf\/.*)/i" 109 | commits: "(^perf:|(IF-[0-9]+ -- perf)).*/i" 110 | 111 | - label: "Style" 112 | sync: true 113 | matcher: 114 | title: ".*(style:|(IF-[0-9]+ -- (style|lint)|lint)).*/i" 115 | body: ".*(style:|styling:|lint:|linting|format:|formatting).*/i" 116 | branch: "(^style\/.*)/i" 117 | baseBranch: "(^style\/.*)/i" 118 | commits: ".*(style:|(IF-[0-9]+ -- style)|lint|formatting.*)/i" 119 | files: 120 | any: 121 | [ 122 | "**/.*prettier.*", 123 | "**/.*eslint.*", 124 | "**/.*stylelint.*", 125 | "**/.*style.*", 126 | "**/.*lint.*", 127 | "**/.*editorconfig.*", 128 | ] 129 | count: 130 | gte: 1 131 | lte: 1000 132 | 133 | - label: "Database" 134 | sync: true 135 | matcher: 136 | title: "(^db:.*|.*sql.*|(IF-[0-9]+ -- db.*))/i" 137 | body: ".*(db:|database:).*/i" 138 | branch: "(^db\/.*)/i" 139 | baseBranch: "(^db\/.*)/i" 140 | commits: "(^db:.*|.*sql|(IF-[0-9]+ -- db.*))/i" 141 | files: 142 | # regex glob to match a file with extension .sql in any directory recursively 143 | any: 144 | [ 145 | "**/*.sql", 146 | "**/*.db", 147 | "**/db/**", 148 | "**/flyway.*", 149 | "**/migrations/**", 150 | "**/*.sqlite.*", 151 | ] 152 | count: 153 | gte: 1 154 | lte: 1000 155 | 156 | - label: "Security" 157 | sync: true 158 | matcher: 159 | title: ".*(CVE|sec:|security).*/i" 160 | body: ".*(CVE|sec:|security).*/i/i" 161 | branch: ".*(CVE|sec:|security).*/i" 162 | baseBranch: ".*(CVE|sec:|security).*/i" 163 | commits: ".*(CVE|sec:|security).*/i" 164 | files: 165 | any: 166 | [ 167 | "CODEOWNERS", 168 | "SECURITY.*", 169 | ".github/settings.yml", 170 | "**/*.pem", 171 | "**/*.crt", 172 | "**/.*password.*", 173 | "**/.*secret.*", 174 | "**/.*token.*", 175 | "**/.*key.*", 176 | ] 177 | count: 178 | gte: 1 179 | lte: 1000 180 | 181 | - label: "Git" 182 | sync: true 183 | matcher: 184 | title: ".*git.*/i" 185 | files: 186 | any: ["**/.git.*", "**/.husky/*"] 187 | count: 188 | gte: 1 189 | lte: 1000 190 | 191 | - label: "Sync-Files" 192 | sync: true 193 | matcher: 194 | title: ".*Sync-Files.*/i" 195 | 196 | - label: "DO NOT MERGE" 197 | sync: true 198 | matcher: 199 | title: ".*(DO NOT MERGE|DONT MERGE|DON'T MERGE).*" 200 | body: ".*(DO NOT MERGE|DONT MERGE|DON'T MERGE).*" 201 | commits: ".*(DO NOT MERGE|DONT MERGE|DON'T MERGE).*" 202 | 203 | checks: 204 | - context: "Merge check" 205 | description: "Disable merging when 'DO NOT MERGE' label is set" 206 | labels: 207 | none: ["DO NOT MERGE"] 208 | -------------------------------------------------------------------------------- /kernel_config.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | set -xe 3 | 4 | # Set config options in kernel 5 | 6 | # Manipulate options in a .config file from the command line. 7 | # Usage: 8 | # $myname options command ... 9 | # commands: 10 | # --enable|-e option Enable option 11 | # --disable|-d option Disable option 12 | # --module|-m option Turn option into a module 13 | # --set-str option string 14 | # Set option to "string" 15 | # --set-val option value 16 | # Set option to value 17 | # --undefine|-u option Undefine option 18 | # --state|-s option Print state of option (n,y,m,undef) 19 | 20 | # --enable-after|-E beforeopt option 21 | # Enable option directly after other option 22 | # --disable-after|-D beforeopt option 23 | # Disable option directly after other option 24 | # --module-after|-M beforeopt option 25 | # Turn option into module directly after other option 26 | 27 | # commands can be repeated multiple times 28 | 29 | # options: 30 | # --file config-file .config file to change (default .config) 31 | # --keep-case|-k Keep next symbols' case (dont' upper-case it) 32 | 33 | # $myname doesn't check the validity of the .config file. This is done at next 34 | # make time. 35 | 36 | # By default, $myname will upper-case the given symbol. Use --keep-case to keep 37 | # the case of all following symbols unchanged. 38 | 39 | # $myname uses 'CONFIG_' as the default symbol prefix. Set the environment 40 | # variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ... 41 | 42 | # Debuginfo is only needed if you plan to use binary object tools like crash, kgdb, and SystemTap on the kernel. 43 | 44 | scripts/config --disable DEBUG_INFO \ 45 | --disable CONFIG_DEBUG_FS \ 46 | --disable CONFIG_HAVE_DMA_API_DEBUG \ 47 | --disable CONFIG_PM_DEBUG \ 48 | --disable CONFIG_PM_ADVANCED_DEBUG \ 49 | --disable CONFIG_PM_SLEEP_DEBUG \ 50 | --disable CONFIG_NFS_DEBUG \ 51 | --disable CONFIG_CIFS_DEBUG \ 52 | --disable CONFIG_DLM_DEBUG \ 53 | --disable CONFIG_SCHED_DEBUG \ 54 | --disable CONFIG_HAVE_DMA_API_DEBUG \ 55 | --disable CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC \ 56 | --disable CONFIG_DEBUG_RODATA \ 57 | --disable CONFIG_DEBUG_BLK_CGROUP \ 58 | --disable CONFIG_CGROUP_DEBUG \ 59 | --disable CONFIG_GRKERNSEC_AUDIT_GROUP \ 60 | --disable CONFIG_GRKERNSEC_AUDIT_GID \ 61 | --disable CONFIG_GRKERNSEC_EXECLOG \ 62 | --disable CONFIG_GRKERNSEC_RESLOG \ 63 | --disable CONFIG_GRKERNSEC_CHROOT_EXECLOG \ 64 | --disable CONFIG_GRKERNSEC_AUDIT_PTRACE \ 65 | --disable CONFIG_GRKERNSEC_AUDIT_CHDIR \ 66 | --disable CONFIG_GRKERNSEC_AUDIT_MOUNT \ 67 | --disable CONFIG_GRKERNSEC_SIGNAL \ 68 | --disable CONFIG_GRKERNSEC_FORKFAIL \ 69 | --disable CONFIG_GRKERNSEC_TIME \ 70 | --disable CONFIG_GRKERNSEC_PROC_IPADDR \ 71 | --disable CONFIG_GRKERNSEC_RWXMAP_LOG 72 | 73 | # Ensure Keys and Signature are unique to this build, see https://lists.debian.org/debian-kernel/2016/04/msg00579.html 74 | scripts/config --disable CONFIG_SYSTEM_TRUSTED_KEYS 75 | 76 | # RTL8821AE is a buggy module 77 | scripts/config --disable RTL8821AE 78 | 79 | 80 | ### Virtualisation Helper ### 81 | 82 | scripts/config --set-str CONFIG_UEVENT_HELPER_PATH "" 83 | scripts/config --set-str CONFIG_DEFAULT_IOSCHED "noop" 84 | scripts/config --enable CONFIG_UEVENT_HELPER 85 | 86 | 87 | ### Storage Helper ### 88 | 89 | scripts/config --enable CONFIG_SCSI_MQ_DEFAULT \ 90 | --enable CONFIG_DM_MQ_DEFAULT \ 91 | --enable CONFIG_DEFAULT_NOOP 92 | 93 | 94 | if [ "$GRSEC" = "true" ]; then 95 | 96 | ### GRSecurity ### 97 | 98 | scripts/config --set-val CONFIG_TASK_SIZE_MAX_SHIFT 47 99 | 100 | scripts/config --enable CONFIG_PAX_USERCOPY_SLABS \ 101 | --enable CONFIG_GRKERNSEC \ 102 | --enable CONFIG_GRKERNSEC_CONFIG_AUTO \ 103 | --enable CONFIG_GRKERNSEC_CONFIG_SERVER \ 104 | --enable CONFIG_GRKERNSEC_CONFIG_VIRT_GUEST \ 105 | --enable CONFIG_GRKERNSEC_CONFIG_VIRT_EPT \ 106 | --enable CONFIG_GRKERNSEC_CONFIG_VIRT_XEN \ 107 | --enable CONFIG_GRKERNSEC_CONFIG_PRIORITY_PERF 108 | 109 | # 110 | # Default Special Groups 111 | # 112 | scripts/config --set-val CONFIG_GRKERNSEC_PROC_GID 1001 \ 113 | --set-val CONFIG_GRKERNSEC_TPE_UNTRUSTED_GID 1005 \ 114 | --set-val CONFIG_GRKERNSEC_SYMLINKOWN_GID 1006 115 | 116 | # 117 | # PaX 118 | # 119 | scripts/config --enable CONFIG_PAX \ 120 | --enable CONFIG_PAX_EI_PAX \ 121 | --enable CONFIG_PAX_PT_PAX_FLAGS \ 122 | --enable CONFIG_PAX_XATTR_PAX_FLAGS \ 123 | --enable CONFIG_PAX_HAVE_ACL_FLAGS 124 | 125 | # 126 | # Non-executable pages 127 | # 128 | scripts/config --enable CONFIG_PAX_NOEXEC \ 129 | --enable CONFIG_PAX_PAGEEXEC \ 130 | --enable CONFIG_PAX_EMUTRAMP \ 131 | --enable CONFIG_PAX_MPROTECT 132 | 133 | scripts/config --set-str CONFIG_PAX_KERNEXEC_PLUGIN_METHOD "" 134 | 135 | # 136 | # Address Space Layout Randomization 137 | # 138 | scripts/config --enable CONFIG_PAX_ASLR \ 139 | --enable CONFIG_PAX_RANDKSTACK \ 140 | --enable CONFIG_PAX_RANDUSTACK \ 141 | --enable CONFIG_PAX_RANDMMAP 142 | 143 | # 144 | # Miscellaneous hardening features 145 | # 146 | scripts/config --enable CONFIG_PAX_REFCOUNT \ 147 | --enable CONFIG_PAX_USERCOPY \ 148 | --enable CONFIG_PAX_SIZE_OVERFLOW \ 149 | --enable CONFIG_PAX_LATENT_ENTROPY 150 | 151 | # 152 | # Memory Protections 153 | # 154 | scripts/config --enable CONFIG_GRKERNSEC_KMEM \ 155 | --enable CONFIG_GRKERNSEC_IO \ 156 | --enable CONFIG_GRKERNSEC_BPF_HARDEN \ 157 | --enable CONFIG_GRKERNSEC_PERF_HARDEN \ 158 | --enable CONFIG_GRKERNSEC_RAND_THREADSTACK \ 159 | --enable CONFIG_GRKERNSEC_PROC_MEMMAP \ 160 | --enable CONFIG_GRKERNSEC_KSTACKOVERFLOW \ 161 | --enable CONFIG_GRKERNSEC_BRUTE \ 162 | --enable CONFIG_GRKERNSEC_MODHARDEN \ 163 | --enable CONFIG_GRKERNSEC_HIDESYM \ 164 | --enable CONFIG_GRKERNSEC_RANDSTRUCT \ 165 | --enable CONFIG_GRKERNSEC_RANDSTRUCT_PERFORMANCE \ 166 | --enable CONFIG_GRKERNSEC_KERN_LOCKOUT 167 | 168 | # 169 | # Role Based Access Control Options 170 | # 171 | scripts/config --set-val CONFIG_GRKERNSEC_ACL_MAXTRIES 3 \ 172 | --set-val CONFIG_GRKERNSEC_ACL_TIMEOUT 30 173 | 174 | # 175 | # Filesystem Protections 176 | # 177 | scripts/config --enable CONFIG_GRKERNSEC_PROC \ 178 | --enable CONFIG_GRKERNSEC_PROC_USERGROUP \ 179 | --enable CONFIG_GRKERNSEC_PROC_ADD \ 180 | --enable CONFIG_GRKERNSEC_LINK \ 181 | --enable CONFIG_GRKERNSEC_SYMLINKOWN \ 182 | --enable CONFIG_GRKERNSEC_FIFO \ 183 | --enable CONFIG_GRKERNSEC_SYSFS_RESTRICT \ 184 | --enable CONFIG_GRKERNSEC_DEVICE_SIDECHANNEL \ 185 | --enable CONFIG_GRKERNSEC_CHROOT \ 186 | --enable CONFIG_GRKERNSEC_CHROOT_MOUNT \ 187 | --enable CONFIG_GRKERNSEC_CHROOT_DOUBLE \ 188 | --enable CONFIG_GRKERNSEC_CHROOT_PIVOT \ 189 | --enable CONFIG_GRKERNSEC_CHROOT_CHDIR \ 190 | --enable CONFIG_GRKERNSEC_CHROOT_CHMOD \ 191 | --enable CONFIG_GRKERNSEC_CHROOT_FCHDIR \ 192 | --enable CONFIG_GRKERNSEC_CHROOT_MKNOD \ 193 | --enable CONFIG_GRKERNSEC_CHROOT_SHMAT \ 194 | --enable CONFIG_GRKERNSEC_CHROOT_UNIX \ 195 | --enable CONFIG_GRKERNSEC_CHROOT_FINDTASK \ 196 | --enable CONFIG_GRKERNSEC_CHROOT_NICE \ 197 | --enable CONFIG_GRKERNSEC_CHROOT_SYSCTL \ 198 | --enable CONFIG_GRKERNSEC_CHROOT_CAPS \ 199 | --enable CONFIG_GRKERNSEC_CHROOT_INITRD 200 | 201 | # 202 | # Kernel Auditing 203 | # 204 | scripts/config --enable CONFIG_GRKERNSEC_RESLOG \ 205 | --enable CONFIG_GRKERNSEC_SIGNAL \ 206 | --enable CONFIG_GRKERNSEC_TIME \ 207 | --enable CONFIG_GRKERNSEC_PROC_IPADDR \ 208 | --enable CONFIG_GRKERNSEC_RWXMAP_LOG 209 | 210 | # 211 | # Executable Protections 212 | # 213 | scripts/config --enable CONFIG_GRKERNSEC_DMESG \ 214 | --enable CONFIG_GRKERNSEC_HARDEN_PTRACE \ 215 | --enable CONFIG_GRKERNSEC_PTRACE_READEXEC \ 216 | --enable CONFIG_GRKERNSEC_SETXID \ 217 | --enable CONFIG_GRKERNSEC_HARDEN_IPC \ 218 | --enable CONFIG_GRKERNSEC_TPE 219 | 220 | scripts/config --set-val CONFIG_GRKERNSEC_TPE_GID 1005 221 | 222 | # 223 | # Network Protections 224 | # 225 | scripts/config --enable CONFIG_GRKERNSEC_BLACKHOLE \ 226 | --enable CONFIG_GRKERNSEC_NO_SIMULT_CONNECT 227 | 228 | # 229 | # Physical Protections 230 | # 231 | scripts/config --enable CONFIG_GRKERNSEC_DENYUSB 232 | 233 | # 234 | # Sysctl Support 235 | # 236 | scripts/config --enable CONFIG_GRKERNSEC_SYSCTL \ 237 | --enable CONFIG_GRKERNSEC_SYSCTL_ON 238 | 239 | # 240 | # Logging Options 241 | # 242 | scripts/config --set-val CONFIG_GRKERNSEC_FLOODTIME 10 \ 243 | --set-val CONFIG_GRKERNSEC_FLOODBURST 6 244 | 245 | # Modules 246 | scripts/config --enable CONFIG_MODULE_SIG \ 247 | --enable CONFIG_MODULE_SIG_SHA256 \ 248 | --enable CONFIG_MODULES_TREE_LOOKUP \ 249 | --enable CONFIG_MODVERSIONS \ 250 | --set-val CONFIG_MODULE_SIG_HASH "sha256" \ 251 | --set-val CONFIG_MODULE_SIG_KEY "" 252 | 253 | fi 254 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![kernel_300](https://cloud.githubusercontent.com/assets/862951/6546050/53636040-c5f7-11e4-94d4-5e2dbfb8a27c.png) 2 | 3 | [![Issue Count](https://codeclimate.com/github/sammcj/kernel-ci/badges/issue_count.svg)](https://codeclimate.com/github/sammcj/kernel-ci) 4 | 5 | ### Linux Kernel CI for Debian 6 | 7 | * Uploads publicly accessable Debian Kernel Packages to [packagecloud.io](https://packagecloud.io/mrmondo/debian-kernel?filter=debs) 8 | * Includes Kernel Watcher that detects new stable kernel releases and triggers builds. 9 | * Supports patching the Kernel with GRSecurity 10 | * Tested with Gitlab-CI and Travis-CI but should work on any CI system. 11 | * Runs in an isolated and disposble docker container. 12 | * No root access required when building with Docker. 13 | * Both the build and the kernels Work with Debian Wheezy (7) and Jessie (8). 14 | * Supports uploading built packages to a remote server and adding them to [reprepro](https://wiki.debian.org/SettingUpSignedAptRepositoryWithReprepro) 15 | * Allows advanced kernel configuration and options 16 | 17 | --- 18 | 19 | 20 | 21 | - [Usage](#usage) 22 | - [Patches](#patches) 23 | - [Optional Configuration](#optional-configuration) 24 | - [TODO:](#todo) 25 | - [Example Output](#example-output) 26 | 27 | 28 | 29 | --- 30 | 31 | ## Usage 32 | 33 | ### Build Kernel Deb 34 | ```bash 35 | ./buildkernel.sh 36 | ``` 37 | 38 | ### Build Kernel Deb with Docker 39 | ```bash 40 | make ci 41 | ``` 42 | After a successfully building the kernel package, the kernel will be copied to /mnt/storage on the host. 43 | 44 | 45 | ## Patches 46 | 47 | Any kernel patches (p0 format) placed in ./patches/ will be applied 48 | 49 | ## Optional Configuration 50 | 51 | **A list of all build options can be found in [kernel_config.sh](https://github.com/sammcj/kernel-ci/blob/master/kernel_config.sh)** 52 | 53 | For example: 54 | 55 | #### APT_UPDATE 56 | Perform an apt-get update and upgrade prior to building 57 | 58 | Default Value: `false` 59 | 60 | #### KERNEL_VERSION 61 | Default Value: Latest STABLE kernel version 62 | 63 | #### VERSION_POSTFIX 64 | For restrictions see the --append-to-version option of make-kpg.c 65 | 66 | Default Value: `-ci` 67 | 68 | #### TRUSTED_FINGERPRINT 69 | Fingerprint of a trusted key the kernel is signed with 70 | See http://www.kernel.org/signature.html 71 | http://lwn.net/Articles/461647/ 72 | 73 | ATTENTION: Make sure you really trust it! 74 | 75 | Default Value: `ABAF 11C6 5A29 70B1 30AB E3C4 79BE 3E43 0041 1886` 76 | 77 | #### SOURCE\_URL_BASE 78 | Where the archive and sources are located 79 | 80 | Default Value: `https://kernel.org/pub/linux/kernel/v4.x` 81 | 82 | #### KEYSERVER 83 | Server used to get the trusted key from. 84 | 85 | Default Value: `hkp://pool.sks-keyservers.net` 86 | 87 | etc... 88 | 89 | #### STOCK_CONFIG 90 | The kernel config to use for the build 91 | 92 | _Note_ if using a modern config such as the 4.5.5 config's provided in this repo, you must be using a modern very of GCC that supports `fstack-protector-strong`, otherwise you will get this error: 93 | 94 | ```bash 95 | Makefile:667: Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: -fstack-protector-strong not supported by compiler 96 | ``` 97 | 98 | ### Post Processing Options 99 | 100 | #### PACKAGECLOUD 101 | Enable pushing to reprepro upon successful build 102 | 103 | Default Value: `false` 104 | 105 | #### PACKAGE\_CLOUD_URL 106 | Must be replaced if you wish to upload to packagecloud.io 107 | 108 | Default Value: `mrmondo/debian-kernel/debian/jessie` 109 | 110 | #### REPREPRO 111 | Enable pushing to reprepro upon successful build 112 | 113 | Default Value: `false` 114 | 115 | #### REPREPRO_HOST 116 | The username and password to login to the reprepro host 117 | 118 | Default Value: `ci@aptproxy` 119 | 120 | #### REPREPO_URL 121 | The URL of the reprepro mirror 122 | 123 | Default Value: `var/vhost/mycoolaptmirror.com/html` 124 | 125 | ## TODO: 126 | * See [issues](https://github.com/sammcj/kernel-ci/issues) 127 | 128 | ## Example Output 129 | ```bash 130 | cd /home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27 && git reset --hard && git clean -fdx && git remote set-url origin https://gitlab-ci-token:blablabla@gitlab.yourcompany.com/systems/kernel.git && git fetch origin 131 | HEAD is now at 9faa7a2 initramfs-tools 132 | From https://gitlab.yourcompany.com/systems/kernel 133 | 9faa7a2..4ec20fd master -> origin/master 134 | cd /home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27 && git reset --hard && git checkout 4ec20fdb1f677a2f51b6e37a92a1fff61434ab52 135 | HEAD is now at 9faa7a2 initramfs-tools 136 | Previous HEAD position was 9faa7a2... initramfs-tools 137 | HEAD is now at 4ec20fd... cleanup 138 | make ci 139 | RUNNING ON int-ci-02 140 | RUNNING AS gitlab_ci_runner 141 | make build 142 | make[1]: Entering directory `/home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27' 143 | docker build -t contyard.yourcompany.com/linux-kernel: . 144 | Sending build context to Docker daemon 519.2 kB 145 | 146 | Sending build context to Docker daemon 147 | Step 0 : FROM contyard.yourcompany.com/wheezy 148 | ---> 38ce0497b79a 149 | Step 1 : MAINTAINER systems 150 | ---> Using cache 151 | ---> 5181ce4604b0 152 | Step 2 : ENV DEBIAN_FRONTEND noninteractive 153 | ---> Using cache 154 | ---> 3b741575bd57 155 | Step 3 : RUN apt-get -qq update && apt-get -qq install fakeroot build-essential kernel-package wget xz-utils gnupg bc devscripts apt-utils initramfs-tools && apt-get clean 156 | ---> Using cache 157 | ---> e9a92e2943ad 158 | Step 4 : RUN mkdir -p /mnt/storage 159 | ---> Running in 4605ab2fa2bf 160 | ---> 902c01ee6f86 161 | Removing intermediate container 4605ab2fa2bf 162 | Step 5 : WORKDIR /app 163 | ---> Running in 5b9d3ab98da3 164 | ---> e86e27a7d592 165 | Removing intermediate container 5b9d3ab98da3 166 | Step 6 : ADD buildkernel.sh /app/buildkernel.sh 167 | ---> 1261802d8c83 168 | Removing intermediate container 8c10c00de0ee 169 | Step 7 : ADD kernel_config /app/.config 170 | ---> 5a8446b33beb 171 | Removing intermediate container 5b872e547af5 172 | Step 8 : RUN chmod +x buildkernel.sh && ./buildkernel.sh 173 | ---> Running in df3c7c8e464d 174 | You need the following packages installed fakeroot make build-essential kernel-package for this script to work 175 | Recieving key ABAF 11C6 5A29 70B1 30AB E3C4 79BE 3E43 0041 1886 from the keyserver... 176 | gpg: keyring `./kernelkey/secring.gpg' created 177 | gpg: keyring `./kernelkey/pubring.gpg' created 178 | gpg: requesting key 00411886 from hkp server pool.sks-keyservers.net 179 | gpg: ./kernelkey/trustdb.gpg: trustdb created 180 | gpg: key 00411886: public key "Linus Torvalds " imported 181 | gpg: no ultimately trusted keys found 182 | gpg: Total number processed: 1 183 | gpg: imported: 1 (RSA: 1) 184 | --2015-01-21 02:32:50-- http://mirror.aarnet.edu.au/pub/ftp.kernel.org/linux/kernel/v3.x/linux-3.18.3.tar.xz 185 | Resolving mirror.aarnet.edu.au (mirror.aarnet.edu.au)... 202.158.214.106, 2001:388:30bc:cafe::beef 186 | Connecting to mirror.aarnet.edu.au (mirror.aarnet.edu.au)|202.158.214.106|:80... connected. 187 | HTTP request sent, awaiting response... 200 OK 188 | Length: 80944856 (77M) [application/x-xz] 189 | Saving to: `linux-3.18.3.tar.xz' 190 | 191 | 0K .......... .......... .......... .......... .......... 0% 128K 10m16s 192 | 50K .......... .......... .......... .......... .......... 0% 320K 7m11s 193 | 100K .......... .......... .......... .......... .......... 0% 638K 5m29s 194 | 150K .......... .......... .......... .......... .......... 0% 639K 4m37s 195 | 200K .......... .......... .......... .......... .......... 0% 641K 4m6s 196 | 250K .......... .......... .......... .......... .......... 0% 42.8M 3m25s 197 | 300K .......... .......... .......... .......... .......... 0% 641K 3m13s 198 | ``` 199 | ... 200 | ```bash 201 | 78950K .......... .......... .......... .......... .......... 99% 641K 0s 202 | 79000K .......... .......... .......... .......... ....... 100% 614K=1m41s 203 | 204 | 2015-01-21 02:34:31 (782 KB/s) - `linux-3.18.3.tar.xz' saved [80944856/80944856] 205 | 206 | --2015-01-21 02:34:31-- http://mirror.aarnet.edu.au/pub/ftp.kernel.org/linux/kernel/v3.x/linux-3.18.3.tar.sign 207 | Resolving mirror.aarnet.edu.au (mirror.aarnet.edu.au)... 202.158.214.106, 2001:388:30bc:cafe::beef 208 | Connecting to mirror.aarnet.edu.au (mirror.aarnet.edu.au)|202.158.214.106|:80... connected. 209 | HTTP request sent, awaiting response... 200 OK 210 | Length: 819 [application/x-tar] 211 | Saving to: `linux-3.18.3.tar.sign' 212 | 213 | 0K 100% 59.6M=0s 214 | 215 | 2015-01-21 02:34:31 (59.6 MB/s) - `linux-3.18.3.tar.sign' saved [819/819] 216 | 217 | Extracting downloaded sources to tar... 218 | Extracting tar... 219 | /app/linux-3.18.3 /app 220 | HOSTCC scripts/basic/fixdep 221 | HOSTCC scripts/kconfig/conf.o 222 | SHIPPED scripts/kconfig/zconf.tab.c 223 | SHIPPED scripts/kconfig/zconf.lex.c 224 | SHIPPED scripts/kconfig/zconf.hash.c 225 | HOSTCC scripts/kconfig/zconf.tab.o 226 | HOSTLD scripts/kconfig/conf 227 | scripts/kconfig/conf --oldconfig Kconfig 228 | # 229 | # configuration written to .config 230 | # 231 | /app 232 | /app/linux-3.18.3 /app 233 | exec make kpkg_version=12.036+nmu3 -f /usr/share/kernel-package/ruleset/minimal.mk debian APPEND_TO_VERSION=-ix INITRD=YES 234 | ====== making target debian/stamp/conf/minimal_debian [new prereqs: ]====== 235 | This is kernel package version 12.036+nmu3. 236 | test -d debian || mkdir debian 237 | test ! -e stamp-building || rm -f stamp-building 238 | install -p -m 755 /usr/share/kernel-package/rules debian/rules 239 | for file in ChangeLog Control Control.bin86 config templates.in rules; do \ 240 | cp -f /usr/share/kernel-package/$file ./debian/; \ 241 | done 242 | for dir in Config docs examples ruleset scripts pkg po; do \ 243 | cp -af /usr/share/kernel-package/$dir ./debian/; \ 244 | done 245 | test -f debian/control || sed -e 's/=V/3.18.3-ix/g' \ 246 | -e 's/=D/3.18.3-ix-10.00.Custom/g' -e 's/=A/amd64/g' \ 247 | -e 's/=SA//g' \ 248 | -e 's/=I//g' \ 249 | -e 's/=CV/3.18/g' \ 250 | -e 's/=M/Unknown Kernel Package Maintainer /g' \ 251 | -e 's/=ST/linux/g' -e 's/=B/x86_64/g' \ 252 | /usr/share/kernel-package/Control > debian/control 253 | test -f debian/changelog || sed -e 's/=V/3.18.3-ix/g' \ 254 | -e 's/=D/3.18.3-ix-10.00.Custom/g' -e 's/=A/amd64/g' \ 255 | -e 's/=ST/linux/g' -e 's/=B/x86_64/g' \ 256 | -e 's/=M/Unknown Kernel Package Maintainer /g' \ 257 | /usr/share/kernel-package/changelog > debian/changelog 258 | chmod 0644 debian/control debian/changelog 259 | test -d ./debian/stamp || mkdir debian/stamp 260 | make -f debian/rules debian/stamp/conf/kernel-conf 261 | make[1]: Entering directory `/app/linux-3.18.3' 262 | ====== making target debian/stamp/conf/kernel-conf [new prereqs: ]====== 263 | make EXTRAVERSION=-ix ARCH=x86_64 \ 264 | oldconfig; 265 | make[2]: Entering directory `/app/linux-3.18.3' 266 | scripts/kconfig/conf --oldconfig Kconfig 267 | # 268 | # configuration written to .config 269 | # 270 | make[2]: Leaving directory `/app/linux-3.18.3' 271 | make EXTRAVERSION=-ix ARCH=x86_64 prepare 272 | make[2]: Entering directory `/app/linux-3.18.3' 273 | scripts/kconfig/conf --silentoldconfig Kconfig 274 | make[2]: Leaving directory `/app/linux-3.18.3' 275 | make[2]: Entering directory `/app/linux-3.18.3' 276 | SYSTBL arch/x86/syscalls/../include/generated/asm/syscalls_32.h 277 | SYSHDR arch/x86/syscalls/../include/generated/asm/unistd_32_ia32.h 278 | SYSHDR arch/x86/syscalls/../include/generated/asm/unistd_64_x32.h 279 | SYSTBL arch/x86/syscalls/../include/generated/asm/syscalls_64.h 280 | SYSHDR arch/x86/syscalls/../include/generated/uapi/asm/unistd_32.h 281 | SYSHDR arch/x86/syscalls/../include/generated/uapi/asm/unistd_64.h 282 | SYSHDR arch/x86/syscalls/../include/generated/uapi/asm/unistd_x32.h 283 | HOSTCC arch/x86/tools/relocs_32.o 284 | HOSTCC arch/x86/tools/relocs_64.o 285 | HOSTCC arch/x86/tools/relocs_common.o 286 | HOSTLD arch/x86/tools/relocs 287 | CHK include/config/kernel.release 288 | UPD include/config/kernel.release 289 | WRAP arch/x86/include/generated/asm/clkdev.h 290 | WRAP arch/x86/include/generated/asm/cputime.h 291 | WRAP arch/x86/include/generated/asm/dma-contiguous.h 292 | WRAP arch/x86/include/generated/asm/early_ioremap.h 293 | WRAP arch/x86/include/generated/asm/mcs_spinlock.h 294 | WRAP arch/x86/include/generated/asm/scatterlist.h 295 | CHK include/generated/uapi/linux/version.h 296 | UPD include/generated/uapi/linux/version.h 297 | CHK include/generated/utsrelease.h 298 | UPD include/generated/utsrelease.h 299 | CC kernel/bounds.s 300 | GEN include/generated/bounds.h 301 | CC arch/x86/kernel/asm-offsets.s 302 | GEN include/generated/asm-offsets.h 303 | CALL scripts/checksyscalls.sh 304 | make[2]: Leaving directory `/app/linux-3.18.3' 305 | echo done > debian/stamp/conf/kernel-conf 306 | make[1]: Leaving directory `/app/linux-3.18.3' 307 | make -f debian/rules debian/stamp/conf/full-changelog 308 | make[1]: Entering directory `/app/linux-3.18.3' 309 | ====== making target debian/stamp/conf/full-changelog [new prereqs: ]====== 310 | for file in ChangeLog Control Control.bin86 config templates.in rules; do \ 311 | cp -f /usr/share/kernel-package/$file ./debian/; \ 312 | done 313 | for dir in Config docs examples ruleset scripts pkg po; do \ 314 | cp -af /usr/share/kernel-package/$dir ./debian/; \ 315 | done 316 | install -p -m 755 /usr/share/kernel-package/rules debian/rules 317 | sed -e 's/=V/3.18.3-ix/g' \ 318 | -e 's/=D/3.18.3-ix-10.00.Custom/g' -e 's/=A/amd64/g' \ 319 | -e 's/=SA//g' \ 320 | -e 's/=I//g' \ 321 | -e 's/=CV/3.18/g' \ 322 | -e 's/=M/Unknown Kernel Package Maintainer /g' \ 323 | -e 's/=ST/linux/g' -e 's/=B/x86_64/g' \ 324 | /usr/share/kernel-package/Control > debian/control 325 | sed -e 's/=V/3.18.3-ix/g' -e 's/=D/3.18.3-ix-10.00.Custom/g' \ 326 | -e 's/=A/amd64/g' -e 's/=M/Unknown Kernel Package Maintainer /g' \ 327 | -e 's/=ST/linux/g' -e 's/=B/x86_64/g' \ 328 | /usr/share/kernel-package/changelog > debian/changelog 329 | chmod 0644 debian/control debian/changelog 330 | make -f debian/rules debian/stamp/conf/kernel-conf 331 | make[2]: Entering directory `/app/linux-3.18.3' 332 | make[2]: `debian/stamp/conf/kernel-conf' is up to date. 333 | make[2]: Leaving directory `/app/linux-3.18.3' 334 | make[1]: Leaving directory `/app/linux-3.18.3' 335 | echo done > debian/stamp/conf/minimal_debian 336 | exec debian/rules APPEND_TO_VERSION=-ix INITRD=YES kernel_image 337 | ====== making target debian/stamp/conf/vars [new prereqs: ]====== 338 | 339 | ====== making target debian/stamp/build/kernel [new prereqs: vars]====== 340 | This is kernel package version 12.036+nmu3. 341 | restore_upstream_debianization 342 | test ! -f scripts/package/builddeb.kpkg-dist || mv -f scripts/package/builddeb.kpkg-dist scripts/package/builddeb 343 | test ! -f scripts/package/Makefile.kpkg-dist || mv -f scripts/package/Makefile.kpkg-dist scripts/package/Makefile 344 | /usr/bin/make -j8 EXTRAVERSION=-ix ARCH=x86_64 \ 345 | bzImage 346 | make[1]: Entering directory `/app/linux-3.18.3' 347 | scripts/kconfig/conf --silentoldconfig Kconfig 348 | make[1]: Leaving directory `/app/linux-3.18.3' 349 | make[1]: Entering directory `/app/linux-3.18.3' 350 | CHK include/config/kernel.release 351 | CHK include/generated/uapi/linux/version.h 352 | CHK include/generated/utsrelease.h 353 | HOSTCC scripts/kallsyms 354 | HOSTCC scripts/conmakehash 355 | HOSTCC scripts/recordmcount 356 | HOSTCC scripts/sortextable 357 | HOSTCC scripts/genksyms/genksyms.o 358 | CC scripts/mod/empty.o 359 | HOSTCC scripts/selinux/genheaders/genheaders 360 | HOSTCC scripts/selinux/mdp/mdp 361 | HOSTCC scripts/mod/mk_elfconfig 362 | CC scripts/mod/devicetable-offsets.s 363 | SHIPPED scripts/genksyms/parse.tab.c 364 | SHIPPED scripts/genksyms/lex.lex.c 365 | GEN scripts/mod/devicetable-offsets.h 366 | MKELF scripts/mod/elfconfig.h 367 | SHIPPED scripts/genksyms/keywords.hash.c 368 | HOSTCC scripts/mod/modpost.o 369 | ``` 370 | ... 371 | ```bash 372 | chmod -R og=rX /app/linux-3.18.3/debian/linux-image-3.18.3-ix 373 | chown -R root:root /app/linux-3.18.3/debian/linux-image-3.18.3-ix 374 | dpkg --build /app/linux-3.18.3/debian/linux-image-3.18.3-ix .. 375 | dpkg-deb: building package `linux-image-3.18.3-ix' in `../linux-image-3.18.3-ix_3.18.3-ix-10.00.Custom_amd64.deb'. 376 | make[2]: Leaving directory `/app/linux-3.18.3' 377 | make[1]: Leaving directory `/app/linux-3.18.3' 378 | /app 379 | Congratulations! You just build a linux kernel. 380 | Use the following command to install it: dpkg -i linux-image-3.18.3-ix*.deb 381 | 382 | real 29m9.675s 383 | user 106m11.252s 384 | sys 11m12.928s 385 | ---> f2bc6838c313 386 | Removing intermediate container df3c7c8e464d 387 | Successfully built f2bc6838c313 388 | Successfully built contyard.yourcompany.com/linux-kernel:... 389 | ``` 390 | ```bash 391 | make push 392 | make[1]: Leaving directory `/home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27' 393 | make push 394 | make[1]: Entering directory `/home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27' 395 | docker run -v /mnt/storage/:/mnt/storage contyard.yourcompany.com/linux-kernel: bash -c "cp *.deb /mnt/storage/" 396 | make[1]: Leaving directory `/home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27' 397 | make clean 398 | make[1]: Entering directory `/home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27' 399 | docker rmi -f contyard.yourcompany.com/linux-kernel: 400 | Untagged: contyard.yourcompany.com/linux-kernel:latest 401 | Deleted: f2bc6838c313d8631914614fdbee4d02bac7ff89d4eddf9943b4d51c54729cde 402 | Deleted: 5a8446b33bebd1206336e8dfb313c4d6cf01c248f21ded23d3bc33915c6df452 403 | Deleted: 1261802d8c8357cbeecc399565e07b407cb77020739a520dc9f186bafac400a3 404 | Deleted: e86e27a7d592e11461dada61908100ceee03951d3777867e9883fe17518a7fe7 405 | Deleted: 902c01ee6f862d684633f3dfc75a46b18a8fae18a87a6a22f8477ed5b019c630 406 | make[1]: Leaving directory `/home/gitlab_ci_runner/gitlab-ci-runner/tmp/builds/project-27' 407 | 408 | Build 409 | ``` 410 | 411 | 412 | ```bash 413 | /mnt/storage ~ ls 414 | linux-image-3.18.3-ix_3.18.3-ix-10.00.Custom_amd64.deb 415 | ``` 416 | -------------------------------------------------------------------------------- /example_patches/stackclash.patch: -------------------------------------------------------------------------------- 1 | From 1be7107fbe18eed3e319a6c3e83c78254b693acb Mon Sep 17 00:00:00 2001 2 | From: Hugh Dickins 3 | Date: Mon, 19 Jun 2017 04:03:24 -0700 4 | Subject: mm: larger stack guard gap, between vmas 5 | 6 | Stack guard page is a useful feature to reduce a risk of stack smashing 7 | into a different mapping. We have been using a single page gap which 8 | is sufficient to prevent having stack adjacent to a different mapping. 9 | But this seems to be insufficient in the light of the stack usage in 10 | userspace. E.g. glibc uses as large as 64kB alloca() in many commonly 11 | used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX] 12 | which is 256kB or stack strings with MAX_ARG_STRLEN. 13 | 14 | This will become especially dangerous for suid binaries and the default 15 | no limit for the stack size limit because those applications can be 16 | tricked to consume a large portion of the stack and a single glibc call 17 | could jump over the guard page. These attacks are not theoretical, 18 | unfortunatelly. 19 | 20 | Make those attacks less probable by increasing the stack guard gap 21 | to 1MB (on systems with 4k pages; but make it depend on the page size 22 | because systems with larger base pages might cap stack allocations in 23 | the PAGE_SIZE units) which should cover larger alloca() and VLA stack 24 | allocations. It is obviously not a full fix because the problem is 25 | somehow inherent, but it should reduce attack space a lot. 26 | 27 | One could argue that the gap size should be configurable from userspace, 28 | but that can be done later when somebody finds that the new 1MB is wrong 29 | for some special case applications. For now, add a kernel command line 30 | option (stack_guard_gap) to specify the stack gap size (in page units). 31 | 32 | Implementation wise, first delete all the old code for stack guard page: 33 | because although we could get away with accounting one extra page in a 34 | stack vma, accounting a larger gap can break userspace - case in point, 35 | a program run with "ulimit -S -v 20000" failed when the 1MB gap was 36 | counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK 37 | and strict non-overcommit mode. 38 | 39 | Instead of keeping gap inside the stack vma, maintain the stack guard 40 | gap as a gap between vmas: using vm_start_gap() in place of vm_start 41 | (or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few 42 | places which need to respect the gap - mainly arch_get_unmapped_area(), 43 | and and the vma tree's subtree_gap support for that. 44 | 45 | Original-patch-by: Oleg Nesterov 46 | Original-patch-by: Michal Hocko 47 | Signed-off-by: Hugh Dickins 48 | Acked-by: Michal Hocko 49 | Tested-by: Helge Deller # parisc 50 | Signed-off-by: Linus Torvalds 51 | --- 52 | Documentation/admin-guide/kernel-parameters.txt | 7 ++ 53 | arch/arc/mm/mmap.c | 2 +- 54 | arch/arm/mm/mmap.c | 4 +- 55 | arch/frv/mm/elf-fdpic.c | 2 +- 56 | arch/mips/mm/mmap.c | 2 +- 57 | arch/parisc/kernel/sys_parisc.c | 15 ++- 58 | arch/powerpc/mm/hugetlbpage-radix.c | 2 +- 59 | arch/powerpc/mm/mmap.c | 4 +- 60 | arch/powerpc/mm/slice.c | 2 +- 61 | arch/s390/mm/mmap.c | 4 +- 62 | arch/sh/mm/mmap.c | 4 +- 63 | arch/sparc/kernel/sys_sparc_64.c | 4 +- 64 | arch/sparc/mm/hugetlbpage.c | 2 +- 65 | arch/tile/mm/hugetlbpage.c | 2 +- 66 | arch/x86/kernel/sys_x86_64.c | 4 +- 67 | arch/x86/mm/hugetlbpage.c | 2 +- 68 | arch/xtensa/kernel/syscall.c | 2 +- 69 | fs/hugetlbfs/inode.c | 2 +- 70 | fs/proc/task_mmu.c | 4 - 71 | include/linux/mm.h | 53 ++++----- 72 | mm/gup.c | 5 - 73 | mm/memory.c | 38 ------ 74 | mm/mmap.c | 149 ++++++++++++++---------- 75 | 23 files changed, 152 insertions(+), 163 deletions(-) 76 | 77 | diff --git Documentation/admin-guide/kernel-parameters.txt Documentation/admin-guide/kernel-parameters.txt 78 | index 0f5c3b4..7737ab5 100644 79 | --- Documentation/admin-guide/kernel-parameters.txt 80 | +++ Documentation/admin-guide/kernel-parameters.txt 81 | @@ -3811,6 +3811,13 @@ 82 | expediting. Set to zero to disable automatic 83 | expediting. 84 | 85 | + stack_guard_gap= [MM] 86 | + override the default stack gap protection. The value 87 | + is in page units and it defines how many pages prior 88 | + to (for stacks growing down) resp. after (for stacks 89 | + growing up) the main stack are reserved for no other 90 | + mapping. Default value is 256 pages. 91 | + 92 | stacktrace [FTRACE] 93 | Enabled the stack tracer on boot up. 94 | 95 | diff --git arch/arc/mm/mmap.c arch/arc/mm/mmap.c 96 | index 3e25e8d..2e13683 100644 97 | --- arch/arc/mm/mmap.c 98 | +++ arch/arc/mm/mmap.c 99 | @@ -65,7 +65,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, 100 | 101 | vma = find_vma(mm, addr); 102 | if (TASK_SIZE - len >= addr && 103 | - (!vma || addr + len <= vma->vm_start)) 104 | + (!vma || addr + len <= vm_start_gap(vma))) 105 | return addr; 106 | } 107 | 108 | diff --git arch/arm/mm/mmap.c arch/arm/mm/mmap.c 109 | index 2239fde..f0701d8 100644 110 | --- arch/arm/mm/mmap.c 111 | +++ arch/arm/mm/mmap.c 112 | @@ -90,7 +90,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, 113 | 114 | vma = find_vma(mm, addr); 115 | if (TASK_SIZE - len >= addr && 116 | - (!vma || addr + len <= vma->vm_start)) 117 | + (!vma || addr + len <= vm_start_gap(vma))) 118 | return addr; 119 | } 120 | 121 | @@ -141,7 +141,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 122 | addr = PAGE_ALIGN(addr); 123 | vma = find_vma(mm, addr); 124 | if (TASK_SIZE - len >= addr && 125 | - (!vma || addr + len <= vma->vm_start)) 126 | + (!vma || addr + len <= vm_start_gap(vma))) 127 | return addr; 128 | } 129 | 130 | diff --git arch/frv/mm/elf-fdpic.c arch/frv/mm/elf-fdpic.c 131 | index da82c25..46aa289 100644 132 | --- arch/frv/mm/elf-fdpic.c 133 | +++ arch/frv/mm/elf-fdpic.c 134 | @@ -75,7 +75,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi 135 | addr = PAGE_ALIGN(addr); 136 | vma = find_vma(current->mm, addr); 137 | if (TASK_SIZE - len >= addr && 138 | - (!vma || addr + len <= vma->vm_start)) 139 | + (!vma || addr + len <= vm_start_gap(vma))) 140 | goto success; 141 | } 142 | 143 | diff --git arch/mips/mm/mmap.c arch/mips/mm/mmap.c 144 | index 64dd8bd..28adeab 100644 145 | --- arch/mips/mm/mmap.c 146 | +++ arch/mips/mm/mmap.c 147 | @@ -93,7 +93,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, 148 | 149 | vma = find_vma(mm, addr); 150 | if (TASK_SIZE - len >= addr && 151 | - (!vma || addr + len <= vma->vm_start)) 152 | + (!vma || addr + len <= vm_start_gap(vma))) 153 | return addr; 154 | } 155 | 156 | diff --git arch/parisc/kernel/sys_parisc.c arch/parisc/kernel/sys_parisc.c 157 | index e528863..378a754 100644 158 | --- arch/parisc/kernel/sys_parisc.c 159 | +++ arch/parisc/kernel/sys_parisc.c 160 | @@ -90,7 +90,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, 161 | unsigned long len, unsigned long pgoff, unsigned long flags) 162 | { 163 | struct mm_struct *mm = current->mm; 164 | - struct vm_area_struct *vma; 165 | + struct vm_area_struct *vma, *prev; 166 | unsigned long task_size = TASK_SIZE; 167 | int do_color_align, last_mmap; 168 | struct vm_unmapped_area_info info; 169 | @@ -117,9 +117,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, 170 | else 171 | addr = PAGE_ALIGN(addr); 172 | 173 | - vma = find_vma(mm, addr); 174 | + vma = find_vma_prev(mm, addr, &prev); 175 | if (task_size - len >= addr && 176 | - (!vma || addr + len <= vma->vm_start)) 177 | + (!vma || addr + len <= vm_start_gap(vma)) && 178 | + (!prev || addr >= vm_end_gap(prev))) 179 | goto found_addr; 180 | } 181 | 182 | @@ -143,7 +144,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 183 | const unsigned long len, const unsigned long pgoff, 184 | const unsigned long flags) 185 | { 186 | - struct vm_area_struct *vma; 187 | + struct vm_area_struct *vma, *prev; 188 | struct mm_struct *mm = current->mm; 189 | unsigned long addr = addr0; 190 | int do_color_align, last_mmap; 191 | @@ -177,9 +178,11 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 192 | addr = COLOR_ALIGN(addr, last_mmap, pgoff); 193 | else 194 | addr = PAGE_ALIGN(addr); 195 | - vma = find_vma(mm, addr); 196 | + 197 | + vma = find_vma_prev(mm, addr, &prev); 198 | if (TASK_SIZE - len >= addr && 199 | - (!vma || addr + len <= vma->vm_start)) 200 | + (!vma || addr + len <= vm_start_gap(vma)) && 201 | + (!prev || addr >= vm_end_gap(prev))) 202 | goto found_addr; 203 | } 204 | 205 | diff --git arch/powerpc/mm/hugetlbpage-radix.c arch/powerpc/mm/hugetlbpage-radix.c 206 | index 6575b9a..a12e863 100644 207 | --- arch/powerpc/mm/hugetlbpage-radix.c 208 | +++ arch/powerpc/mm/hugetlbpage-radix.c 209 | @@ -68,7 +68,7 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, 210 | addr = ALIGN(addr, huge_page_size(h)); 211 | vma = find_vma(mm, addr); 212 | if (mm->task_size - len >= addr && 213 | - (!vma || addr + len <= vma->vm_start)) 214 | + (!vma || addr + len <= vm_start_gap(vma))) 215 | return addr; 216 | } 217 | /* 218 | diff --git arch/powerpc/mm/mmap.c arch/powerpc/mm/mmap.c 219 | index 9dbd2a73..0ee6be4 100644 220 | --- arch/powerpc/mm/mmap.c 221 | +++ arch/powerpc/mm/mmap.c 222 | @@ -112,7 +112,7 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, 223 | addr = PAGE_ALIGN(addr); 224 | vma = find_vma(mm, addr); 225 | if (mm->task_size - len >= addr && addr >= mmap_min_addr && 226 | - (!vma || addr + len <= vma->vm_start)) 227 | + (!vma || addr + len <= vm_start_gap(vma))) 228 | return addr; 229 | } 230 | 231 | @@ -157,7 +157,7 @@ radix__arch_get_unmapped_area_topdown(struct file *filp, 232 | addr = PAGE_ALIGN(addr); 233 | vma = find_vma(mm, addr); 234 | if (mm->task_size - len >= addr && addr >= mmap_min_addr && 235 | - (!vma || addr + len <= vma->vm_start)) 236 | + (!vma || addr + len <= vm_start_gap(vma))) 237 | return addr; 238 | } 239 | 240 | diff --git arch/powerpc/mm/slice.c arch/powerpc/mm/slice.c 241 | index 966b9fc..45f6740 100644 242 | --- arch/powerpc/mm/slice.c 243 | +++ arch/powerpc/mm/slice.c 244 | @@ -99,7 +99,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, 245 | if ((mm->task_size - len) < addr) 246 | return 0; 247 | vma = find_vma(mm, addr); 248 | - return (!vma || (addr + len) <= vma->vm_start); 249 | + return (!vma || (addr + len) <= vm_start_gap(vma)); 250 | } 251 | 252 | static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice) 253 | diff --git arch/s390/mm/mmap.c arch/s390/mm/mmap.c 254 | index b017dae..b854b1d 100644 255 | --- arch/s390/mm/mmap.c 256 | +++ arch/s390/mm/mmap.c 257 | @@ -101,7 +101,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, 258 | addr = PAGE_ALIGN(addr); 259 | vma = find_vma(mm, addr); 260 | if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && 261 | - (!vma || addr + len <= vma->vm_start)) 262 | + (!vma || addr + len <= vm_start_gap(vma))) 263 | goto check_asce_limit; 264 | } 265 | 266 | @@ -151,7 +151,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 267 | addr = PAGE_ALIGN(addr); 268 | vma = find_vma(mm, addr); 269 | if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && 270 | - (!vma || addr + len <= vma->vm_start)) 271 | + (!vma || addr + len <= vm_start_gap(vma))) 272 | goto check_asce_limit; 273 | } 274 | 275 | diff --git arch/sh/mm/mmap.c arch/sh/mm/mmap.c 276 | index 08e7af0..6a1a129 100644 277 | --- arch/sh/mm/mmap.c 278 | +++ arch/sh/mm/mmap.c 279 | @@ -64,7 +64,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, 280 | 281 | vma = find_vma(mm, addr); 282 | if (TASK_SIZE - len >= addr && 283 | - (!vma || addr + len <= vma->vm_start)) 284 | + (!vma || addr + len <= vm_start_gap(vma))) 285 | return addr; 286 | } 287 | 288 | @@ -114,7 +114,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 289 | 290 | vma = find_vma(mm, addr); 291 | if (TASK_SIZE - len >= addr && 292 | - (!vma || addr + len <= vma->vm_start)) 293 | + (!vma || addr + len <= vm_start_gap(vma))) 294 | return addr; 295 | } 296 | 297 | diff --git arch/sparc/kernel/sys_sparc_64.c arch/sparc/kernel/sys_sparc_64.c 298 | index ef4520e..043544d 100644 299 | --- arch/sparc/kernel/sys_sparc_64.c 300 | +++ arch/sparc/kernel/sys_sparc_64.c 301 | @@ -120,7 +120,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi 302 | 303 | vma = find_vma(mm, addr); 304 | if (task_size - len >= addr && 305 | - (!vma || addr + len <= vma->vm_start)) 306 | + (!vma || addr + len <= vm_start_gap(vma))) 307 | return addr; 308 | } 309 | 310 | @@ -183,7 +183,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 311 | 312 | vma = find_vma(mm, addr); 313 | if (task_size - len >= addr && 314 | - (!vma || addr + len <= vma->vm_start)) 315 | + (!vma || addr + len <= vm_start_gap(vma))) 316 | return addr; 317 | } 318 | 319 | diff --git arch/sparc/mm/hugetlbpage.c arch/sparc/mm/hugetlbpage.c 320 | index 7c29d38..88855e3 100644 321 | --- arch/sparc/mm/hugetlbpage.c 322 | +++ arch/sparc/mm/hugetlbpage.c 323 | @@ -120,7 +120,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, 324 | addr = ALIGN(addr, huge_page_size(h)); 325 | vma = find_vma(mm, addr); 326 | if (task_size - len >= addr && 327 | - (!vma || addr + len <= vma->vm_start)) 328 | + (!vma || addr + len <= vm_start_gap(vma))) 329 | return addr; 330 | } 331 | if (mm->get_unmapped_area == arch_get_unmapped_area) 332 | diff --git arch/tile/mm/hugetlbpage.c arch/tile/mm/hugetlbpage.c 333 | index cb10153..03e5cc4 100644 334 | --- arch/tile/mm/hugetlbpage.c 335 | +++ arch/tile/mm/hugetlbpage.c 336 | @@ -233,7 +233,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, 337 | addr = ALIGN(addr, huge_page_size(h)); 338 | vma = find_vma(mm, addr); 339 | if (TASK_SIZE - len >= addr && 340 | - (!vma || addr + len <= vma->vm_start)) 341 | + (!vma || addr + len <= vm_start_gap(vma))) 342 | return addr; 343 | } 344 | if (current->mm->get_unmapped_area == arch_get_unmapped_area) 345 | diff --git arch/x86/kernel/sys_x86_64.c arch/x86/kernel/sys_x86_64.c 346 | index 207b8f2..213ddf3 100644 347 | --- arch/x86/kernel/sys_x86_64.c 348 | +++ arch/x86/kernel/sys_x86_64.c 349 | @@ -144,7 +144,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, 350 | addr = PAGE_ALIGN(addr); 351 | vma = find_vma(mm, addr); 352 | if (end - len >= addr && 353 | - (!vma || addr + len <= vma->vm_start)) 354 | + (!vma || addr + len <= vm_start_gap(vma))) 355 | return addr; 356 | } 357 | 358 | @@ -187,7 +187,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 359 | addr = PAGE_ALIGN(addr); 360 | vma = find_vma(mm, addr); 361 | if (TASK_SIZE - len >= addr && 362 | - (!vma || addr + len <= vma->vm_start)) 363 | + (!vma || addr + len <= vm_start_gap(vma))) 364 | return addr; 365 | } 366 | 367 | diff --git arch/x86/mm/hugetlbpage.c arch/x86/mm/hugetlbpage.c 368 | index 302f43f..adad702 100644 369 | --- arch/x86/mm/hugetlbpage.c 370 | +++ arch/x86/mm/hugetlbpage.c 371 | @@ -148,7 +148,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, 372 | addr = ALIGN(addr, huge_page_size(h)); 373 | vma = find_vma(mm, addr); 374 | if (TASK_SIZE - len >= addr && 375 | - (!vma || addr + len <= vma->vm_start)) 376 | + (!vma || addr + len <= vm_start_gap(vma))) 377 | return addr; 378 | } 379 | if (mm->get_unmapped_area == arch_get_unmapped_area) 380 | diff --git arch/xtensa/kernel/syscall.c arch/xtensa/kernel/syscall.c 381 | index 0693792..74afbf0 100644 382 | --- arch/xtensa/kernel/syscall.c 383 | +++ arch/xtensa/kernel/syscall.c 384 | @@ -88,7 +88,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, 385 | /* At this point: (!vmm || addr < vmm->vm_end). */ 386 | if (TASK_SIZE - len < addr) 387 | return -ENOMEM; 388 | - if (!vmm || addr + len <= vmm->vm_start) 389 | + if (!vmm || addr + len <= vm_start_gap(vmm)) 390 | return addr; 391 | addr = vmm->vm_end; 392 | if (flags & MAP_SHARED) 393 | diff --git fs/hugetlbfs/inode.c fs/hugetlbfs/inode.c 394 | index dde8613..d44f545 100644 395 | --- fs/hugetlbfs/inode.c 396 | +++ fs/hugetlbfs/inode.c 397 | @@ -200,7 +200,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, 398 | addr = ALIGN(addr, huge_page_size(h)); 399 | vma = find_vma(mm, addr); 400 | if (TASK_SIZE - len >= addr && 401 | - (!vma || addr + len <= vma->vm_start)) 402 | + (!vma || addr + len <= vm_start_gap(vma))) 403 | return addr; 404 | } 405 | 406 | diff --git fs/proc/task_mmu.c fs/proc/task_mmu.c 407 | index f0c8b33..520802d 100644 408 | --- fs/proc/task_mmu.c 409 | +++ fs/proc/task_mmu.c 410 | @@ -300,11 +300,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) 411 | 412 | /* We don't show the stack guard page in /proc/maps */ 413 | start = vma->vm_start; 414 | - if (stack_guard_page_start(vma, start)) 415 | - start += PAGE_SIZE; 416 | end = vma->vm_end; 417 | - if (stack_guard_page_end(vma, end)) 418 | - end -= PAGE_SIZE; 419 | 420 | seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); 421 | seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", 422 | diff --git include/linux/mm.h include/linux/mm.h 423 | index b892e95..6f543a4 100644 424 | --- include/linux/mm.h 425 | +++ include/linux/mm.h 426 | @@ -1393,12 +1393,6 @@ int clear_page_dirty_for_io(struct page *page); 427 | 428 | int get_cmdline(struct task_struct *task, char *buffer, int buflen); 429 | 430 | -/* Is the vma a continuation of the stack vma above it? */ 431 | -static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) 432 | -{ 433 | - return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); 434 | -} 435 | - 436 | static inline bool vma_is_anonymous(struct vm_area_struct *vma) 437 | { 438 | return !vma->vm_ops; 439 | @@ -1414,28 +1408,6 @@ bool vma_is_shmem(struct vm_area_struct *vma); 440 | static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; } 441 | #endif 442 | 443 | -static inline int stack_guard_page_start(struct vm_area_struct *vma, 444 | - unsigned long addr) 445 | -{ 446 | - return (vma->vm_flags & VM_GROWSDOWN) && 447 | - (vma->vm_start == addr) && 448 | - !vma_growsdown(vma->vm_prev, addr); 449 | -} 450 | - 451 | -/* Is the vma a continuation of the stack vma below it? */ 452 | -static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr) 453 | -{ 454 | - return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP); 455 | -} 456 | - 457 | -static inline int stack_guard_page_end(struct vm_area_struct *vma, 458 | - unsigned long addr) 459 | -{ 460 | - return (vma->vm_flags & VM_GROWSUP) && 461 | - (vma->vm_end == addr) && 462 | - !vma_growsup(vma->vm_next, addr); 463 | -} 464 | - 465 | int vma_is_stack_for_current(struct vm_area_struct *vma); 466 | 467 | extern unsigned long move_page_tables(struct vm_area_struct *vma, 468 | @@ -2222,6 +2194,7 @@ void page_cache_async_readahead(struct address_space *mapping, 469 | pgoff_t offset, 470 | unsigned long size); 471 | 472 | +extern unsigned long stack_guard_gap; 473 | /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ 474 | extern int expand_stack(struct vm_area_struct *vma, unsigned long address); 475 | 476 | @@ -2250,6 +2223,30 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m 477 | return vma; 478 | } 479 | 480 | +static inline unsigned long vm_start_gap(struct vm_area_struct *vma) 481 | +{ 482 | + unsigned long vm_start = vma->vm_start; 483 | + 484 | + if (vma->vm_flags & VM_GROWSDOWN) { 485 | + vm_start -= stack_guard_gap; 486 | + if (vm_start > vma->vm_start) 487 | + vm_start = 0; 488 | + } 489 | + return vm_start; 490 | +} 491 | + 492 | +static inline unsigned long vm_end_gap(struct vm_area_struct *vma) 493 | +{ 494 | + unsigned long vm_end = vma->vm_end; 495 | + 496 | + if (vma->vm_flags & VM_GROWSUP) { 497 | + vm_end += stack_guard_gap; 498 | + if (vm_end < vma->vm_end) 499 | + vm_end = -PAGE_SIZE; 500 | + } 501 | + return vm_end; 502 | +} 503 | + 504 | static inline unsigned long vma_pages(struct vm_area_struct *vma) 505 | { 506 | return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; 507 | diff --git mm/gup.c mm/gup.c 508 | index b3c7214..576c4df 100644 509 | --- mm/gup.c 510 | +++ mm/gup.c 511 | @@ -387,11 +387,6 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, 512 | /* mlock all present pages, but do not fault in new pages */ 513 | if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK) 514 | return -ENOENT; 515 | - /* For mm_populate(), just skip the stack guard page. */ 516 | - if ((*flags & FOLL_POPULATE) && 517 | - (stack_guard_page_start(vma, address) || 518 | - stack_guard_page_end(vma, address + PAGE_SIZE))) 519 | - return -ENOENT; 520 | if (*flags & FOLL_WRITE) 521 | fault_flags |= FAULT_FLAG_WRITE; 522 | if (*flags & FOLL_REMOTE) 523 | diff --git mm/memory.c mm/memory.c 524 | index 2e65df1..bb11c47 100644 525 | --- mm/memory.c 526 | +++ mm/memory.c 527 | @@ -2855,40 +2855,6 @@ out_release: 528 | } 529 | 530 | /* 531 | - * This is like a special single-page "expand_{down|up}wards()", 532 | - * except we must first make sure that 'address{-|+}PAGE_SIZE' 533 | - * doesn't hit another vma. 534 | - */ 535 | -static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) 536 | -{ 537 | - address &= PAGE_MASK; 538 | - if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { 539 | - struct vm_area_struct *prev = vma->vm_prev; 540 | - 541 | - /* 542 | - * Is there a mapping abutting this one below? 543 | - * 544 | - * That's only ok if it's the same stack mapping 545 | - * that has gotten split.. 546 | - */ 547 | - if (prev && prev->vm_end == address) 548 | - return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; 549 | - 550 | - return expand_downwards(vma, address - PAGE_SIZE); 551 | - } 552 | - if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { 553 | - struct vm_area_struct *next = vma->vm_next; 554 | - 555 | - /* As VM_GROWSDOWN but s/below/above/ */ 556 | - if (next && next->vm_start == address + PAGE_SIZE) 557 | - return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; 558 | - 559 | - return expand_upwards(vma, address + PAGE_SIZE); 560 | - } 561 | - return 0; 562 | -} 563 | - 564 | -/* 565 | * We enter with non-exclusive mmap_sem (to exclude vma changes, 566 | * but allow concurrent faults), and pte mapped but not yet locked. 567 | * We return with mmap_sem still held, but pte unmapped and unlocked. 568 | @@ -2904,10 +2870,6 @@ static int do_anonymous_page(struct vm_fault *vmf) 569 | if (vma->vm_flags & VM_SHARED) 570 | return VM_FAULT_SIGBUS; 571 | 572 | - /* Check if we need to add a guard page to the stack */ 573 | - if (check_stack_guard_page(vma, vmf->address) < 0) 574 | - return VM_FAULT_SIGSEGV; 575 | - 576 | /* 577 | * Use pte_alloc() instead of pte_alloc_map(). We can't run 578 | * pte_offset_map() on pmds where a huge pmd might be created 579 | diff --git mm/mmap.c mm/mmap.c 580 | index f82741e..8e07976 100644 581 | --- mm/mmap.c 582 | +++ mm/mmap.c 583 | @@ -183,6 +183,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) 584 | unsigned long retval; 585 | unsigned long newbrk, oldbrk; 586 | struct mm_struct *mm = current->mm; 587 | + struct vm_area_struct *next; 588 | unsigned long min_brk; 589 | bool populate; 590 | LIST_HEAD(uf); 591 | @@ -229,7 +230,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) 592 | } 593 | 594 | /* Check against existing mmap mappings. */ 595 | - if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) 596 | + next = find_vma(mm, oldbrk); 597 | + if (next && newbrk + PAGE_SIZE > vm_start_gap(next)) 598 | goto out; 599 | 600 | /* Ok, looks good - let it rip. */ 601 | @@ -253,10 +255,22 @@ out: 602 | 603 | static long vma_compute_subtree_gap(struct vm_area_struct *vma) 604 | { 605 | - unsigned long max, subtree_gap; 606 | - max = vma->vm_start; 607 | - if (vma->vm_prev) 608 | - max -= vma->vm_prev->vm_end; 609 | + unsigned long max, prev_end, subtree_gap; 610 | + 611 | + /* 612 | + * Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we 613 | + * allow two stack_guard_gaps between them here, and when choosing 614 | + * an unmapped area; whereas when expanding we only require one. 615 | + * That's a little inconsistent, but keeps the code here simpler. 616 | + */ 617 | + max = vm_start_gap(vma); 618 | + if (vma->vm_prev) { 619 | + prev_end = vm_end_gap(vma->vm_prev); 620 | + if (max > prev_end) 621 | + max -= prev_end; 622 | + else 623 | + max = 0; 624 | + } 625 | if (vma->vm_rb.rb_left) { 626 | subtree_gap = rb_entry(vma->vm_rb.rb_left, 627 | struct vm_area_struct, vm_rb)->rb_subtree_gap; 628 | @@ -352,7 +366,7 @@ static void validate_mm(struct mm_struct *mm) 629 | anon_vma_unlock_read(anon_vma); 630 | } 631 | 632 | - highest_address = vma->vm_end; 633 | + highest_address = vm_end_gap(vma); 634 | vma = vma->vm_next; 635 | i++; 636 | } 637 | @@ -541,7 +555,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, 638 | if (vma->vm_next) 639 | vma_gap_update(vma->vm_next); 640 | else 641 | - mm->highest_vm_end = vma->vm_end; 642 | + mm->highest_vm_end = vm_end_gap(vma); 643 | 644 | /* 645 | * vma->vm_prev wasn't known when we followed the rbtree to find the 646 | @@ -856,7 +870,7 @@ again: 647 | vma_gap_update(vma); 648 | if (end_changed) { 649 | if (!next) 650 | - mm->highest_vm_end = end; 651 | + mm->highest_vm_end = vm_end_gap(vma); 652 | else if (!adjust_next) 653 | vma_gap_update(next); 654 | } 655 | @@ -941,7 +955,7 @@ again: 656 | * mm->highest_vm_end doesn't need any update 657 | * in remove_next == 1 case. 658 | */ 659 | - VM_WARN_ON(mm->highest_vm_end != end); 660 | + VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma)); 661 | } 662 | } 663 | if (insert && file) 664 | @@ -1787,7 +1801,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) 665 | 666 | while (true) { 667 | /* Visit left subtree if it looks promising */ 668 | - gap_end = vma->vm_start; 669 | + gap_end = vm_start_gap(vma); 670 | if (gap_end >= low_limit && vma->vm_rb.rb_left) { 671 | struct vm_area_struct *left = 672 | rb_entry(vma->vm_rb.rb_left, 673 | @@ -1798,7 +1812,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) 674 | } 675 | } 676 | 677 | - gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; 678 | + gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; 679 | check_current: 680 | /* Check if current node has a suitable gap */ 681 | if (gap_start > high_limit) 682 | @@ -1825,8 +1839,8 @@ check_current: 683 | vma = rb_entry(rb_parent(prev), 684 | struct vm_area_struct, vm_rb); 685 | if (prev == vma->vm_rb.rb_left) { 686 | - gap_start = vma->vm_prev->vm_end; 687 | - gap_end = vma->vm_start; 688 | + gap_start = vm_end_gap(vma->vm_prev); 689 | + gap_end = vm_start_gap(vma); 690 | goto check_current; 691 | } 692 | } 693 | @@ -1890,7 +1904,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info) 694 | 695 | while (true) { 696 | /* Visit right subtree if it looks promising */ 697 | - gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; 698 | + gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; 699 | if (gap_start <= high_limit && vma->vm_rb.rb_right) { 700 | struct vm_area_struct *right = 701 | rb_entry(vma->vm_rb.rb_right, 702 | @@ -1903,7 +1917,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info) 703 | 704 | check_current: 705 | /* Check if current node has a suitable gap */ 706 | - gap_end = vma->vm_start; 707 | + gap_end = vm_start_gap(vma); 708 | if (gap_end < low_limit) 709 | return -ENOMEM; 710 | if (gap_start <= high_limit && gap_end - gap_start >= length) 711 | @@ -1929,7 +1943,7 @@ check_current: 712 | struct vm_area_struct, vm_rb); 713 | if (prev == vma->vm_rb.rb_right) { 714 | gap_start = vma->vm_prev ? 715 | - vma->vm_prev->vm_end : 0; 716 | + vm_end_gap(vma->vm_prev) : 0; 717 | goto check_current; 718 | } 719 | } 720 | @@ -1967,7 +1981,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, 721 | unsigned long len, unsigned long pgoff, unsigned long flags) 722 | { 723 | struct mm_struct *mm = current->mm; 724 | - struct vm_area_struct *vma; 725 | + struct vm_area_struct *vma, *prev; 726 | struct vm_unmapped_area_info info; 727 | 728 | if (len > TASK_SIZE - mmap_min_addr) 729 | @@ -1978,9 +1992,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, 730 | 731 | if (addr) { 732 | addr = PAGE_ALIGN(addr); 733 | - vma = find_vma(mm, addr); 734 | + vma = find_vma_prev(mm, addr, &prev); 735 | if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && 736 | - (!vma || addr + len <= vma->vm_start)) 737 | + (!vma || addr + len <= vm_start_gap(vma)) && 738 | + (!prev || addr >= vm_end_gap(prev))) 739 | return addr; 740 | } 741 | 742 | @@ -2003,7 +2018,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 743 | const unsigned long len, const unsigned long pgoff, 744 | const unsigned long flags) 745 | { 746 | - struct vm_area_struct *vma; 747 | + struct vm_area_struct *vma, *prev; 748 | struct mm_struct *mm = current->mm; 749 | unsigned long addr = addr0; 750 | struct vm_unmapped_area_info info; 751 | @@ -2018,9 +2033,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 752 | /* requesting a specific address */ 753 | if (addr) { 754 | addr = PAGE_ALIGN(addr); 755 | - vma = find_vma(mm, addr); 756 | + vma = find_vma_prev(mm, addr, &prev); 757 | if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && 758 | - (!vma || addr + len <= vma->vm_start)) 759 | + (!vma || addr + len <= vm_start_gap(vma)) && 760 | + (!prev || addr >= vm_end_gap(prev))) 761 | return addr; 762 | } 763 | 764 | @@ -2155,21 +2171,19 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr, 765 | * update accounting. This is shared with both the 766 | * grow-up and grow-down cases. 767 | */ 768 | -static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow) 769 | +static int acct_stack_growth(struct vm_area_struct *vma, 770 | + unsigned long size, unsigned long grow) 771 | { 772 | struct mm_struct *mm = vma->vm_mm; 773 | struct rlimit *rlim = current->signal->rlim; 774 | - unsigned long new_start, actual_size; 775 | + unsigned long new_start; 776 | 777 | /* address space limit tests */ 778 | if (!may_expand_vm(mm, vma->vm_flags, grow)) 779 | return -ENOMEM; 780 | 781 | /* Stack limit test */ 782 | - actual_size = size; 783 | - if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) 784 | - actual_size -= PAGE_SIZE; 785 | - if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur)) 786 | + if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur)) 787 | return -ENOMEM; 788 | 789 | /* mlock limit tests */ 790 | @@ -2207,17 +2221,30 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns 791 | int expand_upwards(struct vm_area_struct *vma, unsigned long address) 792 | { 793 | struct mm_struct *mm = vma->vm_mm; 794 | + struct vm_area_struct *next; 795 | + unsigned long gap_addr; 796 | int error = 0; 797 | 798 | if (!(vma->vm_flags & VM_GROWSUP)) 799 | return -EFAULT; 800 | 801 | /* Guard against wrapping around to address 0. */ 802 | - if (address < PAGE_ALIGN(address+4)) 803 | - address = PAGE_ALIGN(address+4); 804 | - else 805 | + address &= PAGE_MASK; 806 | + address += PAGE_SIZE; 807 | + if (!address) 808 | return -ENOMEM; 809 | 810 | + /* Enforce stack_guard_gap */ 811 | + gap_addr = address + stack_guard_gap; 812 | + if (gap_addr < address) 813 | + return -ENOMEM; 814 | + next = vma->vm_next; 815 | + if (next && next->vm_start < gap_addr) { 816 | + if (!(next->vm_flags & VM_GROWSUP)) 817 | + return -ENOMEM; 818 | + /* Check that both stack segments have the same anon_vma? */ 819 | + } 820 | + 821 | /* We must make sure the anon_vma is allocated. */ 822 | if (unlikely(anon_vma_prepare(vma))) 823 | return -ENOMEM; 824 | @@ -2261,7 +2288,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) 825 | if (vma->vm_next) 826 | vma_gap_update(vma->vm_next); 827 | else 828 | - mm->highest_vm_end = address; 829 | + mm->highest_vm_end = vm_end_gap(vma); 830 | spin_unlock(&mm->page_table_lock); 831 | 832 | perf_event_mmap(vma); 833 | @@ -2282,6 +2309,8 @@ int expand_downwards(struct vm_area_struct *vma, 834 | unsigned long address) 835 | { 836 | struct mm_struct *mm = vma->vm_mm; 837 | + struct vm_area_struct *prev; 838 | + unsigned long gap_addr; 839 | int error; 840 | 841 | address &= PAGE_MASK; 842 | @@ -2289,6 +2318,17 @@ int expand_downwards(struct vm_area_struct *vma, 843 | if (error) 844 | return error; 845 | 846 | + /* Enforce stack_guard_gap */ 847 | + gap_addr = address - stack_guard_gap; 848 | + if (gap_addr > address) 849 | + return -ENOMEM; 850 | + prev = vma->vm_prev; 851 | + if (prev && prev->vm_end > gap_addr) { 852 | + if (!(prev->vm_flags & VM_GROWSDOWN)) 853 | + return -ENOMEM; 854 | + /* Check that both stack segments have the same anon_vma? */ 855 | + } 856 | + 857 | /* We must make sure the anon_vma is allocated. */ 858 | if (unlikely(anon_vma_prepare(vma))) 859 | return -ENOMEM; 860 | @@ -2343,28 +2383,25 @@ int expand_downwards(struct vm_area_struct *vma, 861 | return error; 862 | } 863 | 864 | -/* 865 | - * Note how expand_stack() refuses to expand the stack all the way to 866 | - * abut the next virtual mapping, *unless* that mapping itself is also 867 | - * a stack mapping. We want to leave room for a guard page, after all 868 | - * (the guard page itself is not added here, that is done by the 869 | - * actual page faulting logic) 870 | - * 871 | - * This matches the behavior of the guard page logic (see mm/memory.c: 872 | - * check_stack_guard_page()), which only allows the guard page to be 873 | - * removed under these circumstances. 874 | - */ 875 | +/* enforced gap between the expanding stack and other mappings. */ 876 | +unsigned long stack_guard_gap = 256UL<