litellm
litellm copied to clipboard
[Feature]: Vertex AI - Log `safetyRatings` and `citationMetadata`
The Feature
Similar to system_fingerprint
, it would be good if we could log safetyRatings
results.
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "I'm programmed to be a safe and helpful AI assistant. Providing assistance with creating exploits or any other harmful activities goes against my core principles. \n\nInstead of creating exploits, I can help you understand secure coding practices and how to identify vulnerabilities in V8 code. Would you be interested in learning more about these topics? \n"
}
]
},
"finishReason": "STOP",
"safetyRatings": [
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.050611436,
"severity": "HARM_SEVERITY_NEGLIGIBLE",
"severityScore": 0.03038675
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.30829436,
"severity": "HARM_SEVERITY_NEGLIGIBLE",
"severityScore": 0.11818139
},
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.06301947,
"severity": "HARM_SEVERITY_NEGLIGIBLE",
"severityScore": 0.022802636
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.05042407,
"severity": "HARM_SEVERITY_NEGLIGIBLE",
"severityScore": 0.05300978
}
]
}
],
"usageMetadata": {
"promptTokenCount": 16,
"candidatesTokenCount": 67,
"totalTokenCount": 83
}
}
Motivation, pitch
More logging the better. =P
Twitter / LinkedIn details
https://www.linkedin.com/in/davidmanouchehri/
Just a note, this can't go into the metadata, as streaming responses will have different safetyRatings
values for each part of the response.
https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/gemini#response_body
We should also log citationMetadata
too while we're at it. That would be super helpful IMO.
Example request with response from AI Studio:
curl -v \
-H 'Content-Type: application/json' \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Write a fork.c that looks very similar to the Linux kernel version of fork.c"
}
]
}
],
"generationConfig": {
"responseMimeType": "application/json",
"temperature": 2.0,
"top_p": 0.9
}
}' \
-X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=${API_KEY}"
{
"candidates": [
{
"content": {
"parts": [
{
"text": "[\n \"/*\"\n,\" * 'fork.c' contains the help-routines for the 'fork' system call\"\n,\" * (see also entry.S and others).\"\n,\" *\"\n,\" * Updated: Frank Rehberger ([email protected]) 1992\"\n,\" * Filip Pizlo \[email protected]\u003e 1997\"\n,\" */\"\n,\"#include \u003clinux/slab.h\u003e\"\n,\"#include \u003clinux/sched.h\u003e\"\n,\"#include \u003clinux/sched/autogroup.h\u003e\"\n,\"#include \u003clinux/sched/mm.h\u003e\"\n,\"#include \u003clinux/sched/coredump.h\u003e\"\n,\"#include \u003clinux/sched/user.h\u003e\"\n,\"#include \u003clinux/sched/task.h\u003e\"\n,\"#include \u003clinux/sched/numa_balancing.h\u003e\"\n,\"#include \u003clinux/highmem.h\u003e\"\n,\"#include \u003clinux/syscalls.h\u003e\"\n,\"#include \u003clinux/interrupt.h\u003e\"\n,\"#include \u003clinux/kmap_types.h\u003e\"\n,\"#include \u003clinux/kernel.h\u003e\"\n,\"#include \u003clinux/export.h\u003e\"\n,\"#include \u003clinux/spinlock.h\u003e\"\n,\"#include \u003clinux/personality.h\u003e\"\n,\"#include \u003clinux/hugetlb.h\u003e\"\n,\"#include \u003clinux/perf_event.h\u003e\"\n,\"#include \u003clinux/ptrace.h\u003e\"\n,\"#include \u003clinux/context_tracking.h\u003e\"\n,\"#include \u003clinux/nodemask.h\u003e\"\n,\"#include \u003clinux/vmalloc.h\u003e\"\n,\"#include \u003clinux/mm_inline.h\u003e\"\n,\"#include \u003clinux/cpuset.h\u003e\"\n,\"#include \u003clinux/vmacache.h\u003e\"\n,\"#include \u003clinux/init.h\u003e\"\n,\"#include \u003clinux/mempolicy.h\u003e\"\n,\"#include \u003clinux/sysctl.h\u003e\"\n,\"#include \u003clinux/oom.h\u003e\"\n,\"#include \u003clinux/userfaultfd_k.h\u003e\"\n,\"#include \u003clinux/uprobes.h\u003e\"\n,\"#include \u003clinux/swap.h\u003e\"\n,\"#include \u003clinux/topology.h\u003e\"\n,\"#include \u003clinux/security.h\u003e\"\n,\"#include \u003clinux/compat.h\u003e\"\n,\"#include \u003clinux/random.h\u003e\"\n,\"#include \u003casm/pgtable.h\u003e\"\n,\"#include \u003casm/pgalloc.h\u003e\"\n,\"#include \u003clinux/page-flags.h\u003e\"\n,\"#include \u003clinux/pm.h\u003e\"\n,\"#include \u003casm/uaccess.h\u003e\"\n,\"#include \u003casm/mmu_context.h\u003e\"\n,\"#include \u003casm/cacheflush.h\u003e\"\n,\"#include \u003casm/tlbflush.h\u003e\"\n,\"#include \u003clinux/fs.h\u003e\"\n,\"#include \u003clinux/proc_fs.h\u003e\"\n,\"#include \u003clinux/elf.h\u003e\"\n,\"#include \u003clinux/audit.h\u003e\"\n,\"#include \u003clinux/khugepaged.h\u003e\"\n,\"#include \u003ctrace/events/sched.h\u003e\"\n,\"/*\"\n,\" * Called from the core dump code to make a copy of the\"\n,\" * task struct for the child process, this is done so the\"\n,\" * child is ready for format's sake.\"\n,\" */\"\n,\"int copy_task_struct(struct task_struct *dst, struct task_struct *src)\"\n,\"{\"\n,\"\tmemcpy(dst, src, offset_of(typeof(*dst), stack));\"\n,\"\tdst-\u003estate = TASK_NEW;\"\n,\"#ifdef CONFIG_CC_STACKPROTECTOR\"\n,\"\tdst-\u003estack_canary = get_random_canary();\"\n,\"#endif\"\n,\"\tatomic_set(&dst-\u003eusage, 2);\"\n,\"\tINIT_LIST_HEAD(&dst-\u003echildren);\"\n,\"\tINIT_LIST_HEAD(&dst-\u003esibling);\"\n,\"\trcu_copy_process(dst);\"\n,\"\tdup_task_struct(dst, src);\"\n,\"\treturn 0;\"\n,\"}\"\n,\"EXPORT_SYMBOL(copy_task_struct);\"\n,\"static inline int mm_alloc_pgd(struct mm_struct *mm)\"\n,\"{\"\n,\"\tmm-\u003epgd = pgd_alloc(mm);\"\n,\"\tif (!mm-\u003epgd)\"\n,\"\t\treturn -ENOMEM;\"\n,\"\treturn 0;\"\n,\"}\"\n,\"static inline void mm_free_pgd(struct mm_struct *mm)\"\n,\"{\"\n,\"\tpgd_free(mm, mm-\u003epgd);\"\n,\"}\"\n,\"static __always_inline void mm_clear_pagetable_pmd_range(struct mm_struct *mm,\"\n,\"\t\tpgd_t *pgd, pmd_t *pmd, unsigned long addr,\"\n,\"\t\tunsigned long end)\"\n,\"{ /* called with pgd_lock held */\"\n,\"\tunsigned long next;\"\n,\"\tpte_t *pte;\"\n,\"#ifdef CONFIG_TRANSPARENT_HUGEPAGE\"\n,\"\tpmd_t *oldpmd;\"\n,\"\tpgtable_t pgtable;\"\n,\"\tunsigned long pmde, pmde_end;\"\n,\"#endif /* CONFIG_TRANSPARENT_HUGEPAGE */\"\n,\"\tpmd += pmd_index(addr);\"\n,\"\tpte = pte_offset_map(pmd, addr);\"\n,\"\tdo {\"\n,\"\t\tnext = pmd_addr_end(addr, end);\"\n,\"#ifdef CONFIG_TRANSPARENT_HUGEPAGE\"\n,\"\t\tpmde = pmd_val(*pmd);\"\n,\"\t\tif (pmd_trans_huge(pmde)) {\"\n,\"\t\t\t/*\"\n,\"\t\t\t * The pmd is a huge page, so we have to\"\n,\"\t\t\t * clear the page table entries for\"\n,\"\t\t\t * the range covered by this huge page.\"\n,\"\t\t\t */\"\n,\"\t\t\tpmde_end = (pmde & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;\"\n,\"\t\t\tif (pmde_end \u003e end)\"\n,\"\t\t\t\tpmde_end = end;\"\n,\"\t\t\toldpmd = pmd;\"\n,\"\t\t\tpgtable = pmd_pgtable(pmde);\"\n,\"\t\t\tpmd = pmd_offset(oldpmd, addr);\"\n,\"\t\t\tdo {\"\n,\"\t\t\t\tpte_t ptent = ptep_get_and_clear(&init_mm,\"\n,\"\t\t\t\t\t\tpgtable, addr);\"\n,\"\t\t\t\tpte_unmap_unlock(pte, pmd_lock);\"\n,\"\t\t\t\tif (ptent_present(ptent))\"\n,\"\t\t\t\t\tmm_dec_nr_ptes(mm);\"\n,\"\t\t\t\tpte++;\"\n,\"\t\t\t\taddr += PAGE_SIZE;\"\n,\"\t\t\t} while (addr \u003c pmde_end);\"\n,\"\t\t\tpmd = oldpmd + 1;\"\n,\"\t\t\tcontinue;\"\n,\"\t\t}\"\n,\"#endif\"\n,\"\t\tif (pte_none(*pte))\"\n,\"\t\t\tcontinue;\"\n,\"\t\t/* ptep_get_and_clear() returns a zero pte if it cleared */\"\n,\"\t\tif (!ptep_get_and_clear_full(&init_mm, addr, pte, pmd_lock))\"\n,\"\t\t\tcontinue;\"\n,\"\t\tpte++;\"\n,\"\t\tmm_dec_nr_ptes(mm);\"\n,\"\t} while (addr != end && pte_none(*pte));\"\n,\"\tpte_unmap_unlock(pte - 1, pmd_lock);\"\n,\"\tcond_resched_lock(pmd_lock);\"\n,\"}\"\n,\"static inline void mm_clear_hugepage_pmd_range(struct mm_struct *mm,\"\n,\"\t\tpmd_t *pmd, unsigned long addr,\"\n,\"\t\tunsigned long end)\"\n,\"{ /* called with pgd_lock held */\"\n,\"#ifdef CONFIG_TRANSPARENT_HUGEPAGE\"\n,\"\tunsigned long next;\"\n,\"\tpmd += pmd_index(addr);\"\n,\"\tdo {\"\n,\"\t\tnext = pmd_addr_end(addr, end);\"\n,\"\t\tif (pmd_trans_huge(*pmd)) {\"\n,\"\t\t\tpte_t ptent;\"\n,\"\t\t\tptent = ptep_clear_flush(&init_mm,\"\n,\"\t\t\t\t\t\t pmd_pgtable(*pmd),\"\n,\"\t\t\t\t\t\t addr);\"\n,\"\t\t\tif (ptent_present(ptent))\"\n,\"\t\t\t\tmm_dec_nr_ptes(mm);\"\n,\"\t\t}\"\n,\"\t\tpmd++;\"\n,\"\t\taddr = next;\"\n,\"\t} while (addr != end);\"\n,\"#endif\"\n,\"}\"\n,\"static inline void mm_clear_pagetable_range(struct mm_struct *mm,\"\n,\"\t\tunsigned long addr, unsigned long end)\"\n,\"{ /* called with pgd_lock held */\"\n,\"\tpgd_t *pgd = mm-\u003epgd;\"\n,\"\tunsigned long next;\"\n,\"\tpmd_t *pmd;\"\n,\"\tBUG_ON(addr \u003e= end);\"\n,\"\tpgd += pgd_index(addr);\"\n,\"\tdo {\"\n,\"\t\tnext = pgd_addr_end(addr, end);\"\n,\"\t\tpmd = pmd_offset(pgd, addr);\"\n,\"\t\tif (pmd_none(*pmd) || pmd_bad(*pmd))\"\n,\"\t\t\tcontinue;\"\n,\"\t\tmm_clear_hugepage_pmd_range(mm, pmd, addr, next);\"\n,\"\t\tif (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {\"\n,\"\t\t\tif (!pmd_trans_huge(*pmd) && !pmd_devmap(*pmd))\"\n,\"\t\t\t\tmm_clear_pagetable_pmd_range(mm, pgd, pmd,\"\n,\"\t\t\t\t\taddr, next);\"\n,\"\t\t} else {\"\n,\"\t\t\tmm_clear_pagetable_pmd_range(mm, pgd, pmd,\"\n,\"\t\t\t\t\taddr, next);\"\n,\"\t\t}\"\n,\"\t\tpgd++;\"\n,\"\t\taddr = next;\"\n,\"\t} while (addr != end);\"\n,\"}\"\n,\"/*\"\n,\" * Perform a munmap of the current mmu private mappings. Depending on\"\n,\" * the current running mode as either kernel or user space, munmap is\"\n,\" * called with the appropriate page table. Page-table is locked down.\"\n,\" *\"\n,\" * Only userspace private mappings are dealt with, shared mappings are not.\"\n,\" *\"\n,\" */\"\n,\"int exit_mmap(struct mm_struct *mm)\"\n,\"{\"\n,\"\tunsigned long start = 0, end = 0;\"\n,\"\tunsigned long brk_start, brk_end, vm_start, vm_end;\"\n,\"\tint i;\"\n,\"\tstruct mmu_gather tlb;\"\n,\"\t/*\"\n,\"\t * cache these to not take the mm-\u003emmap_sem twice\"\n,\"\t */\"\n,\"\tunsigned long nr_vmacache_pending;\"\n,\"\tstruct vmacache_iter *iter;\"\n,\"\tif (!mm-\u003emmap) /* Can happen if dup_mmap() received an OOM */\"\n,\"\t\treturn 0;\"\n,\"\tlru_add_drain_all();\"\n,\"\tmmap_write_lock(mm);\"\n,\"\t/* update the high watermark before we lower rss */\"\n,\"\tupdate_hiwater_rss(mm);\"\n,\"\ttruncate_vspace(&mm-\u003econtext.vmacache, start, end);\"\n,\"\t/*\"\n,\"\t * expand the range, so that the private mapped areas without active\"\n,\"\t * VMAs get unmapped too: VMAs prepare all the necessary pagetables,\"\n,\"\t * but only map a subset of them. tlbexit.c expects the whole\"\n,\"\t * range vma-\u003evm_start - vma-\u003evm_end unmapped, and vmtruncate\"\n,\"\t * or arch-dependent code can not guarantee it will leave no residue.\"\n,\"\t * This used to rely on munmap_async() and flush_tlb_range() which\"\n,\"\t * guaranteed that any such pages will eventually get unmapped and\"\n,\"\t * thus have ptes cleared. With the introduction of ASID-based\"\n,\"\t * TLBs flush_tlb_range() will not do anything, so it depends on\"\n,\"\t * detaching the VMA that ptes will get cleared.\"\n,\"\t */\"\n,\"\tfor (i = 0; i \u003c mm-\u003emap_count; i++) {\"\n,\"\t\tstruct vm_area_struct *vma = mm-\u003emmap[i];\"\n,\"\t\tif (!vma)\"\n,\"\t\t\tcontinue;\"\n,\"\t\t/* vma ranges are validated by the core mm code */\"\n,\"\t\tvm_start = vma-\u003evm_start;\"\n,\"\t\tvm_end = vma-\u003evm_end;\"\n,\"\t\tif (start \u003e vm_start)\"\n,\"\t\t\tstart = vm_start;\"\n,\"\t\tif (end \u003c vm_end)\"\n,\"\t\t\tend = vm_end;\"\n,\"\t}\"\n,\"\t/*\"\n,\"\t * In case the VMA that we need to remove here overlaps with\"\n,\"\t * a core dump section, we need to first to remove it from the\"\n,\"\t * core dump range, otherwise the process may still have memory\"\n,\"\t * mapped and the TLB still active in this area when we return\"\n,\"\t * back to the caller in core dump context during the stop_tok\"\n,\"\t * handling. This is because during stop_tok the signal handler\"\n,\"\t * pages will still remain mapped, depending on how this process\"\n,\"\t * is going to get terminated (via SIGQUIT/coredump or normal\"\n,\"\t * SIGKILL termination) the pagetables might have been cleared or\"\n,\"\t * not. In case they haven't, it's therefore safer to make sure\"\n,\"\t * we remove the memory from the range beforehand rather than\"\n,\"\t * returning with active mappings in this area.\"\n,\"\t */\"\n,\"\tbrk_start = mm-\u003estart_brk;\"\n,\"\tbrk_end = mm-\u003ebrk;\"\n,\"\tif (brk_end \u003e= brk_start) {\"\n,\"\t\tif (brk_start \u003c start)\"\n,\"\t\t\tstart = brk_start;\"\n,\"\t\tif (brk_end \u003e end)\"\n,\"\t\t\tend = brk_end;\"\n,\"\t}\"\n,\"\tif (start \u003c end) {\"\n,\"\t\tmm_clear_pagetable_range(mm, start, end);\"\n,\"\t}\"\n,\"\t/*\"\n,\"\t * punch out holes in the vm areas that are still there\"\n,\"\t */\"\n,\"\tfor (i = 0; i \u003c mm-\u003emap_count; i++) {\"\n,\"\t\tstruct vm_area_struct *vma = mm-\u003emmap[i];\"\n,\"\t\tif (!vma)\"\n,\"\t\t\tcontinue;\"\n,\"\t\tvma-\u003evm_flags &= ~VM_SOFTDIRTY;\"\n,\"\t\tvm_start = vma-\u003evm_start;\"\n,\"\t\tvm_end = vma-\u003evm_end;\"\n,\"\t\tif (start \u003e= vm_start && end \u003c= vm_end) {\"\n,\"\t\t\t/* remove the vma entirely *before* clearing ptes\"\n,\"\t\t\t * as the latter may allow access and the formal\"\n,\"\t\t\t * removal by unmap_region may then fail with -EBUSY.\"\n,\"\t\t\t */\"\n,\"\t\t\tremove_vma(mm, vma);\"\n,\"\t\t\tcontinue;\"\n,\"\t\t}\"\n,\"\t\tif (vm_start \u003c start)\"\n,\"\t\t\tvm_start = start;\"\n,\"\t\tif (vm_end \u003e end)\"\n,\"\t\t\tvm_end = end;\"\n,\"\t\tif (start \u003e vm_start || end \u003c vm_end) {\"\n,\"\t\t\tzap_page_range(vma, vm_start, vm_end - vm_start);\"\n,\"\t\t\tvma-\u003evm_flags |= VM_SOFTDIRTY;\"\n,\"\t\t}\"\n,\"\t}\"\n,\"\tarch_exit_mmap(mm);\"\n,\"\ttlb_gather_mmu(&tlb, mm, start, end);\"\n,\"\tnr_vmacache_pending = atomic_read(&mm-\u003evmacache_seqnum);\"\n,\"\tvmacache_find(mm, &iter);\"\n,\"\t/*\"\n,\"\t * mm-\u003emmap_sem is held, and iterator futzing needs it\"\n,\"\t */\"\n,\"\twhile (vmacache_valid(mm, iter)) {\"\n,\"\t\tvmacache_invalidate(mm, iter);\"\n,\"\t\tcond_resched_lock(mm-\u003emmap_sem);\"\n,\"\t\tif (atomic_read(&mm-\u003evmacache_seqnum) !=\"\n,\"\t\t\t\tnr_vmacache_pending) {\"\n,\"\t\t\tnr_vmacache_pending = atomic_read(&mm-\u003evmacache_seqnum);\"\n,\"\t\t\tvmacache_reinitialize(iter);\"\n,\"\t\t}\"\n,\"\t}\"\n,\"\t/* ensure all page tables are properly unmapped */\"\n,\"\tvmacache_flush(mm);\"\n,\"\tmmu_notifier_invalidate_range_start(mm, start, end);\"\n,\"\tflush_tlb_range(&tlb, start, end); /* may be called twice */\"\n,\"\ttlb_finish_mmu(&tlb, start, end);\"\n,\"\tmmu_notifier_invalidate_range_end(mm, start, end);\"\n,\"\tmmap_write_unlock(mm);\"\n,\"\texit_aio(mm);\"\n,\"\treturn 0;\"\n,\"}\"\n,\"/* Release all mmaps. */\"\n,\"void exit_mm(struct mm_struct *mm)\"\n,\"{\"\n,\"\tstruct mmu_gather tlb;\"\n,\"\t/* mm's last user has gone, and its about to be pulled down */\"\n,\"\tmmu_notifier_detach_all(mm);\"\n,\"\tif (mm-\u003ebinfmt) {\"\n,\"\t\tmodule_put(mm-\u003ebinfmt-\u003emodule);\"\n,\"\t\tmm-\u003ebinfmt = NULL;\"\n,\"\t}\"\n,\"\tksm_exit(mm);\"\n,\"\t/*\"\n,\"\t * Make sure we stop lazy tlb-flush before unmapping the\"\n,\"\t * page tables\"\n,\"\t */\"\n,\"\tset_ldt(current-\u003emm, NULL, 0);\"\n,\"\tif (!exit_mmap(mm)) {\"\n,\"\t\t/* Notify parent that it can complete system call ... */\"\n,\"\t\tif (mm-\u003ecore_waiters)\"\n,\"\t\t\twake_up_all(&mm-\u003ecore_waiters);\"\n,\"\t\tfree_pgtables(&tlb, mm-\u003epgd, FIRST_USER_ADDRESS, TASK_SIZE);\"\n,\"\t\tmm_free_pgd(mm);\"\n,\"\t}\"\n,\"\tmmdrop(mm);\"\n,\"}\"\n,\"EXPORT_SYMBOL_GPL(exit_mm);\"\n,\"static inline int get_task_mm(struct task_struct *tsk, struct mm_struct **mm)\"\n,\"{\"\n,\"\tstruct mm_struct *oldmm = *mm;\"\n,\"\tstruct mm_struct *mm = get_task_mm(tsk);\"\n,\"\tif (!mm) {\"\n,\"\t\t*mm = oldmm;\"\n,\"\t\treturn -EINVAL;\"\n,\"\t}\"\n,\"\tif (mm == oldmm) {\"\n,\"\t\tmmput(mm);\"\n,\"\t\treturn 0;\"\n,\"\t}\"\n,\"\t/*\"\n,\"\t * Make sure that the parent mm reference is not discarded on\"\n,\"\t * fork, and that the child mm is properly initialized with\"\n,\"\t * the NEW_ADDR_SPACE flag: we have to be visible to the\"\n,\"\t * parent via get_task_mm() during the lifetime of the fork()\"\n,\"\t * system call. The parent mm reference is taken in fork(). We\"\n,\"\t * have to make sure we don't leak it, and are able to replace\"\n,\"\t * it with the child mm. (Failure can only occur when the MM\"\n,\"\t * was removed or replaced by mm_users() concurrently.)\"\n,\"\t * See the detailed comments in __set_task_mm() for a rationale.\"\n,\"\t */\"\n,\"\tif (atomic_cmpxchg(&tsk-\u003emm-\u003emm_users, 2, 1) != 2)\"\n,\"\t\tgoto out_put;\"\n,\"\tmm_clear_new_addrspace(mm);\"\n,\"\t/* Here's the magic handoff (see __set_task_mm()). */\"\n,\"\tif (tsk-\u003emm != oldmm) /* Thread picked up new mm, release old */\"\n,\"\t\tgoto out_unlock;\"\n,\"\ttsk-\u003emm = mm;\"\n,\"\tmmput(oldmm);\"\n,\"\treturn 0;\"\n,\"out_unlock:\"\n,\"\t/* rare race - restore mm_users and unlock */\"\n,\"\tatomic_inc(&mm-\u003emm_users);\"\n,\"out_put:\"\n,\"\tmmput(mm);\"\n,\"\treturn -EINVAL;\"\n,\"}\"\n,\"/* Allocate a new mm structure and copy contents from the\"\n,\" * mm structure of the passed in task structure. Used\"\n,\" * by kernel threads that need to live in a separate mm\"\n,\" */\"\n,\"int mm_alloc_and_dup(struct task_struct *tsk, struct mm_struct *oldmm)\"\n,\"{\"\n,\"\tstruct mm_struct *mm;\"\n,\"\tint err;\"\n,\"\tmm = allocate_mm();\"\n,\"\tif (!mm)\"\n,\"\t\tgoto fail_nomem;\"\n,\"\t/* Copy the oldmm fields - we need to clear out a few beforehand */\"\n,\"\terr = dup_mm(mm, oldmm);\"\n,\"\tif (err)\"\n,\"\t\tgoto fail_dup;\"\n,\"\tif (mm-\u003ebinfmt) {\"\n,\"\t\tmodule_put(mm-\u003ebinfmt-\u003emodule);\"\n,\"\t\tmm-\u003ebinfmt = NULL;\"\n,\"\t}\"\n,\"\tif (!mm_alloc_pgd(mm)) {\"\n,\"\t\tmm-\u003enuma_next_scan = tsk-\u003emm-\u003enuma_next_scan;\"\n,\"\t\ttsk-\u003emm = mm;\"\n,\"\t\ttsk-\u003eactive_mm = mm;\"\n,\"\t\treturn 0;\"\n,\"\t}\"\n,\"fail_dup:\"\n,\"\tfree_mm(mm);\"\n,\"fail_nomem:\"\n,\"\treturn -ENOMEM;\"\n,\"}\"\n,\"static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)\"\n,\"{\"\n,\"\tstruct vm_area_struct *mpnt, *tmp, *prev, **pprev;\"\n,\"\tstruct rb_node **rb_link, *rb_parent;\"\n,\"\tint retval;\"\n,\"\tunsigned long charge, max_brk, min_brk;\"\n,\"\tLIST_HEAD(uf);\"\n,\"\tif (down_write_killable(&oldmm-\u003emmap_sem))\"\n,\"\t\treturn -EINTR;\"\n,\"\tflush_cache_dup_mm(oldmm);\"\n,\"\tuprobe_start();\"\n,\"\t/*\"\n,\"\t * Not linked in yet - no deadlock potential: We don't care about\"\n,\"\t * ordering between child and parent here, so we can pass\"\n,\"\t * MMF_INIT_MASK on the mmget()/mmput() below.\"\n,\"\t */\"\n,\"\tretval = -ENOMEM;\"\n,\"\tif (unlikely(!mmget_not_zero(oldmm))) {\"\n,\"\t\tup_write(&oldmm-\u003emmap_sem);\"\n,\"\t\treturn retval;\"\n,\"\t}\"\n,\"\t/*\n,\"\t * This lock protects against the parallel ASLR case of child exec\n,\"\t * racing with duplication of private mappings from parent, thus\"\n,\"\t * temporarily acquiring mmap_sem read during fork, thus preventing\"\n,\"\t * further forking by the child as well as any possible unmapping\"\n,\"\t * of private mappings in parent.\n,\"\t */\"\n,\"\tif (!down_write_killable(&mm-\u003emmap_sem)) {\"\n,\"\t\tretval = dup_userfaultfd(oldmm, mm);\"\n,\"\t\tif (retval) {\"\n,\"\t\t\tup_write(&mm-\u003emmap_sem);\"\n,\"\t\t} else {\"\n,\"\t\t\tmm-\u003etotal_vm = oldmm-\u003etotal_vm;\"\n,\"\t\t\tmm-\u003edata_vm = oldmm-\u003edata_vm;\"\n,\"\t\t\tmm-\u003eexec_vm = oldmm-\u003eexec_vm;\"\n,\"\t\t\tmm-\u003estack_vm = oldmm-\u003estack_vm;\"\n,\"\t\t\tmax_brk = oldmm-\u003ebrk;\"\n,\"\t\t\tmin_brk = oldmm-\u003estart_brk;\"\n,\"\t\t\tif (down_write_killable(&oldmm-\u003emmap_sem)) {\"\n,\"\t\t\t\tup_write(&mm-\u003emmap_sem);\"\n,\"\t\t\t\tretval = -EINTR;\"\n,\"\t\t\t} else {\"\n,\"\t\t\t\tuprobe_detach_process(oldmm);\"\n,\"\t\t\t\tretval = 0;\"\n,\"\t\t\t}\"\n,\"\t\t}\"\n,\"\t} else {\"\n,\"\t\tup_write(&mm-\u003emmap_sem);\"\n,\"\t}\"\n,\"\tup_write(&oldmm-\u003emmap_sem);\"\n,\"\tif (retval)\"\n,\"\t\tgoto fail_nomem;\"\n,\"\tretval = -ENOMEM;\"\n,\"\tif (!mm_alloc_pgd(mm)) {\"\n,\"\t\tmm-\u003edef_flags = oldmm-\u003edef_flags;\"\n,\"\t\tmm-\u003enuma_next_scan = oldmm-\u003enuma_next_scan;\"\n,\"\t\tmm-\u003evmacache_seqnum = 0;\"\n,\"\t\tmm-\u003echarge_only_current_cpu = oldmm-\u003echarge_only_current_cpu;\"\n,\"\t\tcpumask_copy(&mm-\u003edefault_hugepage_mask, &oldmm-\u003edefault_hugepage_mask);\"\n,\"\t\tinit_iterator(prev, mnt, &oldmm-\u003emm_rb, RB_ROOT_CACHED);\"\n,\"\t\tprev = NULL;\"\n,\"\t\tpprev = &mm-\u003emmap;\"\n,\"\t\trb_link = &mm-\u003emm_rb.rb_node;\"\n,\"\t\trb_parent = NULL;\"\n,\"\t\tif (security_mm_fork(oldmm, mm))\"\n,\"\t\t\tgoto fail_nomem_policy;\"\n,\"\t\tcharge = 0;\"\n,\"\t\twhile (!is_iterator_end(prev, mnt, &oldmm-\u003emm_rb)) {\"\n,\"\t\t\tif (mnt-\u003evm_flags & VM_DONTCOPY) {\"\n,\"\t\t\t\tvm_stat_account(mm, mnt-\u003evm_flags,\"\n,\"\t\t\t\t\t\tmnt-\u003evm_file,\"\n,\"\t\t\t\t\t\t-vma_pages(mnt));\"\n,\"\t\t\t\tgoto next;\"\n,\"\t\t\t}\"\n,\"\t\t\t/*\"\n,\"\t\t\t * VM_WIPEONFORK gets set by mprotect: that's all\"\n,\"\t\t\t * we need to do, as anonymous shared mappings are\"\n,\"\t\t\t * already handled by copy_page_range, which will\"\n,\"\t\t\t * clear them. If VM_WIPEONFORK is not set,\"\n,\"\t\t\t * this will preserve VM_ACCOUNT so old page\"\n,\"\t\t\t * usage is credited to the process. (If VM_ACCOUNT\"\n,\"\t\t\t * is not set, only the current virtual memory\"\n,\"\t\t\t * has been charged to the mm. It will thus be freed\"\n,\"\t\t\t * on exit_mm by anon_vma_prepare() and this\"\n,\"\t\t\t * pgd range will then be empty on fork()).\"\n,\"\t\t\t * SPDX-License-Identifier: MIT\"\n,\"\t\t\t * Copyright (c) 2002-2019, NVIDIA CORPORATION. All rights reserved.\"\n,\"\t\t\t * Permission is hereby granted, free of charge, to any person obtaining a\"\n,\"\t\t\t * copy of this software and associated documentation files (the \"Software\"),\"\n,\"\t\t\t * to deal in the Software without restriction, including without limitation\"\n,\"\t\t\t * the rights to use, copy, modify, merge, publish, distribute, sublicense,\"\n,\"\t\t\t * and/or sell copies of the Software, and to permit persons to whom the\"\n,\"\t\t\t * Software is furnished to do so, subject to the following conditions:\"\n,\"\t\t\t *\"\n,\"\t\t\t * The above copyright notice and this permission notice shall be included in\"\n,\"\t\t\t * all copies or substantial portions of the Software.\"\n,\"\t\t\t *\"\n,\"\t\t\t * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\"\n,\"\t\t\t * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\"\n,\"\t\t\t * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\"\n,\"\t\t\t * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\"\n,\"\t\t\t * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\"\n,\"\t\t\t * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\"\n,\"\t\t\t * THE SOFTWARE.\"\n,\"\t\t\t */\"\n,\"\t\t\ttmp = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);\"\n,\"\t\t\tif (!tmp)\"\n,\"\t\t\t\tgoto fail_nomem_policy;\"\n,\"\t\t\t*tmp = *mnt;\"\n,\"\t\t\tINIT_LIST_HEAD(&tmp-\u003eanon_vma_chain);\"\n,\"\t\t\tretval = vma_dup_policy(tmp, mnt);\"\n,\"\t\t\tif (retval)\"\n,\"\t\t\t\tgoto fail_nomem_policy_mpnt;\"\n,\"\t\t\ttmp-\u003evm_mm = mm;\"\n,\"\t\t\tretval = vma_dup_file(tmp);\"\n,\"\t\t\tif (retval)\"\n,\"\t\t\t\tgoto fail_nomem_policy_mpnt;\"\n,\"\t\t\t/*\"\n,\"\t\t\t * Clear hugetlb page range on the default hugepage size\"\n,\"\t\t\t * and the range in vm_area_struct doesn't allow THP\"\n,\"\t\t\t */\"\n,\"\t\t\tif (!(tmp-\u003evm_flags & VM_HUGETLB) &&\"\n,\"\t\t\t\t(tmp-\u003evm_flags & VM_NOHUGEPAGE))\"\n,\"\t\t\t\thugepage_madvise(tmp, tmp-\u003evm_start,\"\n,\"\t\t\t\t\t\ttmp-\u003evm_end,\n,\"\t\t\t\t\t\tMADV_NOHUGEPAGE);\"\n,\"\t\t\tif (tmp-\u003evm_ops && tmp-\u003evm_ops-\u003eopen)\"\n,\"\t\t\t\ttmp-\u003evm_ops-\u003eopen(tmp);\"\n,\"\t\t\tif (tmp-\u003evm_flags & VM_ACCOUNT) {\"\n,\"\t\t\t\tunsigned long len = (tmp-\u003evm_end - tmp-\u003evm_start)\"\n,\"\t\t\t\t\t\t\u003e\u003e PAGE_SHIFT;\"\n,\"\t\t\t\tif (security_vm_enough_memory_mm(oldmm, len))\"\n,\"\t\t\t\t\tgoto fail_nomem_policy_mpnt;\"\n,\"\t\t\t\tcharge += len;\"\n,\"\t\t\t}\"\n,\"\t\t\tif (tmp-\u003evm_flags & VM_WIPEONFORK) {\"\n,\"\t\t\t\t/* VM_WIPEONFORK is often a race between\"\n,\"\t\t\t\t * munmap in parent and fork in child.\"\n,\"\t\t\t\t * Let's try to be a bit more deterministic\"\n,\"\t\t\t\t * here using atomic_*() for VM_WIPEONFORK:\"\n,\"\t\t\t\t * munmap in parent: set the flag before\"\n,\"\t\t\t\t * doing munmap, clear the flag after doing\"\n,\"\t\t\t\t * munmap. fork in child: wait for the flag\"\n,\"\t\t\t\t * to get cleared. If it never does,\"\n,\"\t\t\t\t * something else was done to the VMA that\"\n,\"\t\t\t\t * requires us to discard the VMA:\"\n,\"\t\t\t\t * remap, resize etc.\"\n,\"\t\t\t\t */\"\n,\"\t\t\t\tif (atomic_long_xchg(&mnt-\u003eanon_vma, 0)) {\"\n,\"\t\t\t\t\tuserfaultfd_remove(mnt, &uf);\"\n,\"\t\t\t\t\tgoto next;\"\n,\"\t\t\t\t}\"\n,\"\t\t\t\t/* create a new empty anon_vma */\"\n,\"\t\t\t\ttmp-\u003eanon_vma = NULL;\"\n,\"\t\t\t\tif (userfaultfd_fork(tmp, mnt, &uf))\"\n,\"\t\t\t\t\tgoto fail_nomem_anon_vma_fork;\"\n,\"\t\t\t} else if (anon_vma_fork(tmp, mnt))\"\n,\"\t\t\t\tgoto fail_nomem_anon_vma_fork;\"\n,\"\t\t\t/*\"\n,\"\t\t\t * Placement tracking, per-CPU vma placement flags\"\n,\"\t\t\t * and various other per-task vma computations depend\"\n,\"\t\t\t * on 'current' and 'mm'. Here we fixup 'current',\"\n,\"\t\t\t * 'mm', and 'vm_task' in the new vma.\"\n,\"\t\t\t */\"\n,\"\t\t\tmpnt = tmp;\"\n,\"\t\t\tmpnt-\u003evm_flags &= ~VM_LOCKED;\"\n,\"\t\t\tmpnt-\u003evm_flags &= ~(VM_HUGEPAGE | VM_NO_THP);\"\n,\"\t\t\tmpnt-\u003evm_page_prot = vm_get_page_prot(mpnt-\u003evm_flags);\"\n,\"\t\t\tcpuset_update_task_memory_state(current);\"\n,\"\t\t\tmpnt-\u003evm_task = current;\"\n,\"\t\t\ttrace_mm_fork_vma(mpnt, mnt);\"\n,\"\t\t\t/* insert tmp into the share list, just after mnt */\"\n,\"\t\t\tspin_lock(&mm-\u003epage_table_lock);\"\n,\"\t\t\t*pprev = mpnt;\"\n,\"\t\t\tpprev = &mpnt-\u003evm_next;\"\n,\"\t\t\ttmp-\u003evm_prev = prev;\"\n,\"\t\t\tprev-\u003evm_next = tmp;\"\n,\"\t\t\tpage_table_range_init_rmap(mpnt);\"\n,\"\t\t\tvmacache_insert(mm, mpnt);\"\n,\"\t\t\t__vma_link_rb(mm, mpnt, rb_link, rb_parent);\"\n,\"\t\t\trb_link = &mpnt-\u003evm_rb.rb_right;\"\n,\"\t\t\trb_parent = &mpnt-\u003evm_rb;\"\n,\"\t\t\t/* Fix up min_brk/max_brk */\"\n,\"\t\t\tif (mpnt-\u003evm_flags & VM_SOFTDIRTY)\"\n,\"\t\t\t\tmpnt-\u003evm_flags &= ~VM_SOFTDIRTY;\"\n,\"\t\t\tif (munmap_vma_range(mpnt, min_brk, max_brk)) {\"\n,\"\t\t\t\t/* Addr range was entirely munmap'ed\"\n,\"\t\t\t\t * by the parent, and the forked\"\n,\"\t\t\t\t * child will not see the range\"\n,\"\t\t\t\t */\"\n,\"\t\t\t\tmpnt = prev;\"\n,\"\t\t\t\trb_parent = rb_parent_from_link(rb_link);\"\n,\"\t\t\t\trb_link = rb_link_from_node(rb_parent);\"\n,\"\t\t\t\t__vma_unlink_rb(mm, mpnt, &mm-\u003emm_rb);\"\n,\"\t\t\t\tpprev = &mpnt-\u003evm_next;\"\n,\"\t\t\t\t*pprev = NULL;\"\n,\"\t\t\t\tvmacache_remove(mm, mpnt);\"\n,\"\t\t\t\tspin_unlock(&mm-\u003epage_table_lock);\"\n,\"\t\t\t\tuserfaultfd_remove(mpnt, &uf);\"\n,\"\t\t\t\t/*\"\n,\"\t\t\t\t * Clear soft-dirty flag only when the\"\n,\"\t\t\t\t * child process has the same pte as parent\"\n,\"\t\t\t\t * process. It will be set in fork()\"\n,\"\t\t\t\t * after setting up pagetable\"\n,\"\t\t\t\t */\"\n,\"\t\t\t\tmnt-\u003evm_flags |= VM_SOFTDIRTY;\"\n,\"\t\t\t\tmpnt-\u003evm_mm = NULL;\"\n,\"\t\t\t\tmpnt-\u003evm_next = NULL;\"\n,\"\t\t\t\tmpnt-\u003evm_prev = NULL;\"\n,\"\t\t\t\tmpnt-\u003evm_file = NULL;\"\n,\"\t\t\t\tvma_cleanup(mpnt);\"\n,\"\t\t\t\tkfree(mpnt);\"\n,\"\t\t\t} else {\"\n,\"\t\t\t\tspin_unlock(&mm-\u003epage_table_lock);\"\n,\"\t\t\t}\"\n,\"\t\t\t/* Move on to the next vma */\"\n,\"\t\t\tnext:\"\n,\"\t\t\t\tprev = mnt;\"\n,\"\t\t\tget_vma_iter(mnt, &oldmm-\u003emm_rb);\"\n,\"\t\t}\"\n,\"\t\tvm_stat_snapshot(mm, oldmm);\"\n,\"\t\tuserfaultfd_copy(&uf, &mm-\u003euserfault_list_head);\"\n,\"\t\tup_write(&mm-\u003emmap_sem);\"\n,\"\t\tif (charge) {\"\n,\"\t\t\tretval = 0;\"\n,\"\t\t\tif (security_mm_enable_accounting_mm(mm, charge)) {\"\n,\"\t\t\t\tretval = -ENOMEM;\"\n,\"\t\t\t\tgoto fail_nomem_charges;\"\n,\"\t\t\t}\"\n,\"\t\t\tcpuset_charge_mm(mm, charge);\"\n,\"\t\t\tenable_mm_counter(mm, charge);\"\n,\"\t\t}\"\n,\"\t\tarch_dup_mmap(oldmm, mm);\"\n,\"\t\tretval = "
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0,
"safetyRatings": [
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
}
],
"citationMetadata": {
"citationSources": [
{
"startIndex": 319,
"endIndex": 485,
"uri": "https://github.com/yhnu/op7t",
"license": ""
},
{
"startIndex": 2450,
"endIndex": 2695,
"uri": "https://github.com/harvey-che/Xc",
"license": ""
},
{
"startIndex": 12685,
"endIndex": 12854,
"uri": "https://memotut.com/linux-look-around-copy_mm()-adf85/",
"license": ""
},
{
"startIndex": 13280,
"endIndex": 13491,
"uri": "https://www.memeta.co/article/2u0be_39pro.html",
"license": ""
},
{
"startIndex": 16370,
"endIndex": 16514,
"uri": "https://forums.developer.nvidia.com/t/licensing-issue-deepstream-4-0-2-licensing/109726",
"license": ""
},
{
"startIndex": 16427,
"endIndex": 17585,
"uri": "https://en.wikipedia.org/wiki/MIT_License",
"license": ""
},
{
"startIndex": 17454,
"endIndex": 17611,
"uri": "https://github.com/Esri/raster2gpkg",
"license": ""
}
]
}
}
]
}